Merge remote-tracking branch 'pfdo/drm-rcar-for-v3.12' into drm-next
authorDave Airlie <airlied@redhat.com>
Sun, 18 Aug 2013 23:24:13 +0000 (09:24 +1000)
committerDave Airlie <airlied@redhat.com>
Sun, 18 Aug 2013 23:24:13 +0000 (09:24 +1000)
Merge the rcar stable branch that is being shared with the arm-soc tree.

Signed-off-by: Dave Airlie <airlied@redhat.com>
* pfdo/drm-rcar-for-v3.12: (220 commits)
  drm/rcar-du: Add FBDEV emulation support
  drm/rcar-du: Add internal LVDS encoder support
  drm/rcar-du: Configure RGB output routing to DPAD0
  drm/rcar-du: Rework output routing support
  drm/rcar-du: Add support for DEFR8 register
  drm/rcar-du: Add support for multiple groups
  drm/rcar-du: Fix buffer pitch alignment for R8A7790 DU
  drm/rcar-du: Add support for the R8A7790 DU
  drm/rcar-du: Move output routing configuration to group
  drm/rcar-du: Remove register definitions for the second channel
  drm/rcar-du: Use dynamic number of CRTCs instead of CRTCs array size
  drm/rcar-du: Introduce CRTCs groups
  drm/rcar-du: Rename rcar_du_plane_(init|register) to rcar_du_planes_*
  drm/rcar-du: Create rcar_du_planes structure
  drm/rcar-du: Rename platform data fields to match what they describe
  drm/rcar-du: Merge LVDS and VGA encoder code
  drm/rcar-du: Split VGA encoder and connector
  drm/rcar-du: Split LVDS encoder and connector
  drm/rcar-du: Clarify comment regarding plane Y source coordinate
  drm/rcar-du: Support per-CRTC clock and IRQ
  ...

Conflicts:
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/qxl/qxl_release.c

258 files changed:
Documentation/devicetree/bindings/clock/imx27-clock.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/ja_JP/HOWTO
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/boot/dts/atlas6.dtsi
arch/arm/boot/dts/imx28-apx4devkit.dts
arch/arm/boot/dts/imx28-evk.dts
arch/arm/boot/dts/imx28-m28evk.dts
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx51-babbage.dts
arch/arm/boot/dts/imx53-mba53.dts
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/prima2.dtsi
arch/arm/boot/dts/stih416-pinctrl.dtsi
arch/arm/boot/dts/stih416.dtsi
arch/arm/boot/dts/twl4030.dtsi
arch/arm/boot/dts/vf610.dtsi
arch/arm/common/edma.c
arch/arm/configs/da8xx_omapl_defconfig
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/nhk8815_defconfig
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/include/mach/memory.h
arch/arm/mach-exynos/pm.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-vf610.c
arch/arm/mach-imx/mx27.h
arch/arm/mach-keystone/keystone.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-s3c24xx/clock-s3c2410.c
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-sti/Kconfig
arch/arm/mach-zynq/common.c
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/include/plat/clock.h
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/plat-samsung/pm.c
arch/arm64/include/asm/thread_info.h
arch/arm64/include/asm/virt.h
arch/arm64/kernel/entry.S
arch/arm64/kernel/process.c
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_cache.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/eeh_sysfs.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci-hotplug.c
arch/powerpc/kernel/pci_of_scan.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/hash_native_64.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power8-pmu.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/ras.c
arch/x86/crypto/Makefile
arch/x86/crypto/crct10dif-pcl-asm_64.S [deleted file]
arch/x86/crypto/crct10dif-pclmul_glue.c [deleted file]
crypto/Kconfig
crypto/Makefile
crypto/crct10dif.c [deleted file]
crypto/tcrypt.c
crypto/testmgr.c
crypto/testmgr.h
drivers/acpi/internal.h
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/ahci_imx.c [new file with mode: 0644]
drivers/ata/ata_piix.c
drivers/ata/libata-scsi.c
drivers/ata/sata_inic162x.c
drivers/cpufreq/intel_pstate.c
drivers/crypto/caam/caamhash.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/i5100_edac.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/qxl/qxl_cmd.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_draw.c
drivers/gpu/drm/qxl/qxl_drv.h
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_fence.c
drivers/gpu/drm/qxl/qxl_gem.c
drivers/gpu/drm/qxl/qxl_image.c
drivers/gpu/drm/qxl/qxl_ioctl.c
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/qxl/qxl_object.h
drivers/gpu/drm/qxl/qxl_release.c
drivers/gpu/drm/qxl/qxl_ttm.c
drivers/gpu/drm/radeon/atombios_dp.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_combios.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/rcar-du/Kconfig
drivers/gpu/drm/rcar-du/Makefile
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_crtc.h
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_drv.h
drivers/gpu/drm/rcar-du/rcar_du_encoder.c [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_encoder.h [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_group.c [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_group.h [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_kms.h
drivers/gpu/drm/rcar-du/rcar_du_lvds.c [deleted file]
drivers/gpu/drm/rcar-du/rcar_du_lvds.h [deleted file]
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/rcar-du/rcar_du_plane.h
drivers/gpu/drm/rcar-du/rcar_du_regs.h
drivers/gpu/drm/rcar-du/rcar_du_vga.c [deleted file]
drivers/gpu/drm/rcar-du/rcar_du_vga.h [deleted file]
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_du_vgacon.h [new file with mode: 0644]
drivers/gpu/drm/rcar-du/rcar_lvds_regs.h [new file with mode: 0644]
drivers/hv/hv_balloon.c
drivers/hv/vmbus_drv.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/misc/atmel-ssc.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/init.c
drivers/mmc/host/pxamci.c
drivers/of/irq.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/pinctrl/core.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/sh-pfc/pfc-sh73a0.c
drivers/pinctrl/sirf/pinctrl-atlas6.c
drivers/scsi/isci/request.c
drivers/scsi/isci/task.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/sd.c
drivers/staging/android/logger.c
drivers/staging/comedi/TODO
drivers/staging/comedi/comedi_fops.c
drivers/staging/frontier/alphatrack.c
drivers/staging/gdm72xx/gdm_qos.c
drivers/staging/imx-drm/Kconfig
drivers/staging/tidspbridge/pmgr/dbll.c
drivers/staging/zram/zram_drv.c
drivers/tty/serial/8250/8250_early.c
drivers/tty/serial/Kconfig
drivers/tty/synclinkmp.c
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/f_ncm.c
drivers/usb/gadget/f_phonet.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/f_subset.c
drivers/usb/gadget/fotg210-udc.c
drivers/usb/gadget/mv_u3d_core.c
drivers/usb/gadget/udc-core.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/pci-quirks.h
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/phy/phy-omap-usb3.c
drivers/usb/phy/phy-samsung-usb2.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/storage/unusual_devs.h
drivers/video/backlight/max8925_bl.c
fs/nfsd/vfs.c
fs/xfs/xfs_dinode.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_log_recover.c
include/acpi/video.h
include/dt-bindings/clock/vf610-clock.h
include/dt-bindings/pinctrl/am33xx.h
include/linux/acpi.h
include/linux/cgroup.h
include/linux/cgroup_subsys.h
include/linux/crc-t10dif.h
include/linux/edac.h
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
include/linux/platform_data/mmc-pxamci.h
include/linux/platform_data/rcar-du.h
include/linux/shdma-base.h
include/linux/usb.h
include/uapi/linux/usb/ch11.h
kernel/cgroup.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h
lib/Kconfig
lib/crc-t10dif.c
sound/pci/hda/patch_sigmatel.c
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/codecs/max98088.c
sound/soc/codecs/sgtl5000.c
sound/soc/soc-core.c
sound/soc/tegra/tegra20_ac97.c
sound/soc/tegra/tegra20_spdif.c
sound/usb/6fire/pcm.c
sound/usb/hiface/pcm.c
tools/hv/hv_kvp_daemon.c

index ab1a56e9de9dc5eea34126c907054c4c775c1885..7a2070393732aa84fc40d7a41220b4531a325248 100644 (file)
@@ -98,6 +98,7 @@ clocks and IDs.
        fpm                  83
        mpll_osc_sel         84
        mpll_sel             85
+       spll_gate            86
 
 Examples:
 
index d5a79caec147d36f993c769ddab2a6c15fb0686a..366ce9b872407e1dfb1964079da4fe95d6094df4 100644 (file)
@@ -26,6 +26,7 @@ est   ESTeem Wireless Modems
 fsl    Freescale Semiconductor
 GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+hisilicon      Hisilicon Limited.
 hp     Hewlett Packard
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
@@ -43,6 +44,7 @@ nxp   NXP Semiconductors
 onnn   ON Semiconductor Corp.
 picochip       Picochip Ltd
 powervr        PowerVR (deprecated, use img)
+qca    Qualcomm Atheros, Inc.
 qcom   Qualcomm, Inc.
 ralink Mediatek/Ralink Technology Corp.
 ramtron        Ramtron International
index 050d37fe6d40a566f684891a626e17d519144472..8148a47fc70e17cbf76be1c6d88ad09f16c983b9 100644 (file)
@@ -11,14 +11,14 @@ for non English (read: Japanese) speakers and is not intended as a
 fork. So if you have any comments or updates for this file, please try
 to update the original English file first.
 
-Last Updated: 2011/03/31
+Last Updated: 2013/07/19
 ==================================
 これは、
-linux-2.6.38/Documentation/HOWTO
+linux-3.10/Documentation/HOWTO
 の和訳です。
 
-翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日: 2011/3/28
+翻訳団体: JF プロジェクト < http://linuxjf.sourceforge.jp/ >
+翻訳日: 2013/7/19
 翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
 校正者: 松倉さん <nbh--mats at nifty dot com>
          小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
@@ -245,7 +245,7 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
 自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
 できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
 ます-
-       http://sosdg.org/~qiyong/lxr/
+       http://lxr.linux.no/+trees
 
 開発プロセス
 -----------------------
@@ -253,24 +253,24 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
 Linux カーネルの開発プロセスは現在幾つかの異なるメインカーネル「ブラン
 チ」と多数のサブシステム毎のカーネルブランチから構成されます。
 これらのブランチとは-
-  - メインの 2.6.x カーネルツリー
-  - 2.6.x.y -stable カーネルツリー
-  - 2.6.x -git カーネルパッチ
+  - メインの 3.x カーネルツリー
+  - 3.x.y -stable カーネルツリー
+  - 3.x -git カーネルパッチ
   - サブシステム毎のカーネルツリーとパッチ
-  - 統合テストのための 2.6.x -next カーネルツリー
+  - 統合テストのための 3.x -next カーネルツリー
 
-2.6.x カーネルツリー
+3.x カーネルツリー
 -----------------
 
-2.6.x カーネルは Linus Torvalds によってメンテナンスされ、kernel.org
-の pub/linux/kernel/v2.6/ ディレクトリに存在します。この開発プロセスは
+3.x カーネルは Linus Torvalds によってメンテナンスされ、kernel.org
+の pub/linux/kernel/v3.x/ ディレクトリに存在します。この開発プロセスは
 以下のとおり-
 
   - 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
     この期間中に、メンテナ達は Linus に大きな差分を送ることができます。
     このような差分は通常 -next カーネルに数週間含まれてきたパッチです。
     大きな変更は git(カーネルのソース管理ツール、詳細は
-    http://git-scm.com/  参照) を使って送るのが好ましいやり方ですが、パッ
+    http://git-scm.com/ 参照) を使って送るのが好ましいやり方ですが、パッ
     チファイルの形式のまま送るのでも十分です。
 
   - 2週間後、-rc1 カーネルがリリースされ、この後にはカーネル全体の安定
@@ -302,20 +302,20 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
   実に認識されたバグの状況によりリリースされるのであり、前もって決めら
   れた計画によってリリースされるものではないからです。」
 
-2.6.x.y -stable カーネルツリー
+3.x.y -stable カーネルツリー
 ---------------------------
 
-バージョン番号が4つの数字に分かれているカーネルは -stable カーネルです。
-これには、2.6.x カーネルで見つかったセキュリティ問題や重大な後戻りに対
+バージョン番号が3つの数字に分かれているカーネルは -stable カーネルです。
+これには、3.x カーネルで見つかったセキュリティ問題や重大な後戻りに対
 する比較的小さい重要な修正が含まれます。
 
 これは、開発/実験的バージョンのテストに協力することに興味が無く、
 最新の安定したカーネルを使いたいユーザに推奨するブランチです。
 
-もし、2.6.x.y カーネルが存在しない場合には、番号が一番大きい 2.6.x が
+もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
 最新の安定版カーネルです。
 
-2.6.x.y は "stable" チーム <stable@kernel.org> でメンテされており、必
+3.x.y は "stable" チーム <stable@kernel.org> でメンテされており、必
 要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
 た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
 の場合はこれに対してだいたいの場合、すぐにリリースがされます。
@@ -324,7 +324,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
 イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ
 リースプロセスがどう動くかが記述されています。
 
-2.6.x -git パッチ
+3.x -git パッチ
 ------------------
 
 git リポジトリで管理されているLinus のカーネルツリーの毎日のスナップ
@@ -358,14 +358,14 @@ quilt シリーズとして公開されているパッチキューも使われ
 をつけることができます。大部分のこれらの patchwork のサイトは
 http://patchwork.kernel.org/ でリストされています。
 
-統合テストのための 2.6.x -next カーネルツリー
+統合テストのための 3.x -next カーネルツリー
 ---------------------------------------------
 
-サブシステムツリーの更新内容がメインラインの 2.6.x ツリーにマージされ
+サブシステムツリーの更新内容がメインラインの 3.x ツリーにマージされ
 る前に、それらは統合テストされる必要があります。この目的のため、実質的
 に全サブシステムツリーからほぼ毎日プルされてできる特別なテスト用のリ
 ポジトリが存在します-
-       http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+       http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
        http://linux.f-seidel.de/linux-next/pmwiki/
 
 このやり方によって、-next カーネルは次のマージ機会でどんなものがメイン
index 5d3facfd78993eeda6d4484f44675471b32f545a..a26b10e52aea18cf39b61095cc563cd940ff1dac 100644 (file)
@@ -3622,11 +3622,9 @@ F:       drivers/isdn/gigaset/
 F:     include/uapi/linux/gigaset_dev.h
 
 GPIO SUBSYSTEM
-M:     Grant Likely <grant.likely@linaro.org>
 M:     Linus Walleij <linus.walleij@linaro.org>
 S:     Maintained
 L:     linux-gpio@vger.kernel.org
-T:     git git://git.secretlab.ca/git/linux-2.6.git
 F:     Documentation/gpio.txt
 F:     drivers/gpio/
 F:     include/linux/gpio*
@@ -4472,8 +4470,6 @@ F:        drivers/irqchip/
 
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
 M:     Benjamin Herrenschmidt <benh@kernel.crashing.org>
-M:     Grant Likely <grant.likely@linaro.org>
-T:     git git://git.secretlab.ca/git/linux-2.6.git irqdomain/next
 S:     Maintained
 F:     Documentation/IRQ-domain.txt
 F:     include/linux/irqdomain.h
@@ -4990,7 +4986,7 @@ F:        arch/powerpc/platforms/44x/
 
 LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
 L:     linuxppc-dev@lists.ozlabs.org
-S:     Unmaintained
+S:     Orphan
 F:     arch/powerpc/*/*virtex*
 F:     arch/powerpc/*/*/*virtex*
 
@@ -5886,7 +5882,7 @@ OMAP DEVICE TREE SUPPORT
 M:     Benoît Cousson <b-cousson@ti.com>
 M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
-L:     devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers)
+L:     devicetree@vger.kernel.org
 S:     Maintained
 F:     arch/arm/boot/dts/*omap*
 F:     arch/arm/boot/dts/*am3*
@@ -6050,17 +6046,28 @@ F:      drivers/i2c/busses/i2c-ocores.c
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
 M:     Rob Herring <rob.herring@calxeda.com>
-L:     devicetree-discuss@lists.ozlabs.org (moderated for non-subscribers)
+L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
 S:     Maintained
-F:     Documentation/devicetree
-F:     drivers/of
+F:     drivers/of/
 F:     include/linux/of*.h
-F:     scripts/dtc
+F:     scripts/dtc/
 K:     of_get_property
 K:     of_match_table
 
+OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
+M:     Rob Herring <rob.herring@calxeda.com>
+M:     Pawel Moll <pawel.moll@arm.com>
+M:     Mark Rutland <mark.rutland@arm.com>
+M:     Stephen Warren <swarren@wwwdotorg.org>
+M:     Ian Campbell <ian.campbell@citrix.com>
+L:     devicetree@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/
+F:     arch/*/boot/dts/
+F:     include/dt-bindings/
+
 OPENRISC ARCHITECTURE
 M:     Jonas Bonn <jonas@southpole.se>
 W:     http://openrisc.net
@@ -7746,7 +7753,6 @@ F:        drivers/clk/spear/
 
 SPI SUBSYSTEM
 M:     Mark Brown <broonie@kernel.org>
-M:     Grant Likely <grant.likely@linaro.org>
 L:     linux-spi@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
 Q:     http://patchwork.kernel.org/project/spi-devel-general/list/
@@ -7812,7 +7818,7 @@ F:        drivers/staging/asus_oled/
 
 STAGING - COMEDI
 M:     Ian Abbott <abbotti@mev.co.uk>
-M:     Mori Hess <fmhess@users.sourceforge.net>
+M:     H Hartley Sweeten <hsweeten@visionengravers.com>
 S:     Odd Fixes
 F:     drivers/staging/comedi/
 
@@ -9288,7 +9294,7 @@ S:        Maintained
 F:     drivers/net/ethernet/xilinx/xilinx_axienet*
 
 XILINX SYSTEMACE DRIVER
-S:     Unmaintained
+S:     Orphan
 F:     drivers/block/xsysace.c
 
 XILINX UARTLITE SERIAL DRIVER
index a35f72a420c030da7e4b107f296c4402bd9cb162..95a8e55feceb1830aa85061336e4e93423e22363 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Linux for Workgroups
 
 # *DOCUMENTATION*
index ba412e02ec0c492abed190202cab324d976d0eec..37c0f4e978d48c8e7928e0a9931b77b6fd4b6be5 100644 (file)
@@ -1600,8 +1600,7 @@ config LOCAL_TIMERS
 config ARCH_NR_GPIO
        int
        default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
-       default 512 if SOC_OMAP5
-       default 512 if ARCH_KEYSTONE
+       default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5
        default 392 if ARCH_U8500
        default 352 if ARCH_VT8500
        default 288 if ARCH_SUNXI
index 9866cd736deea9143ac684b3c5d5313e658ab391..a0f2721ea583bbc358452e7e415c0eadc353e2d6 100644 (file)
                                                 sirf,function = "usp0";
                                         };
                                 };
+                               usp0_uart_nostreamctrl_pins_a: usp0@1 {
+                                        usp0 {
+                                                sirf,pins = "usp0_uart_nostreamctrl_grp";
+                                                sirf,function = "usp0_uart_nostreamctrl";
+                                        };
+                                };
                                 usp1_pins_a: usp1@0 {
                                         usp1 {
                                                 sirf,pins = "usp1grp";
                                                 sirf,function = "pulse_count";
                                         };
                                 };
-                                cko0_rst_pins_a: cko0_rst@0 {
-                                        cko0_rst {
-                                                sirf,pins = "cko0_rstgrp";
-                                                sirf,function = "cko0_rst";
+                                cko0_pins_a: cko0@0 {
+                                        cko0 {
+                                                sirf,pins = "cko0grp";
+                                                sirf,function = "cko0";
                                         };
                                 };
-                                cko1_rst_pins_a: cko1_rst@0 {
-                                        cko1_rst {
-                                                sirf,pins = "cko1_rstgrp";
-                                                sirf,function = "cko1_rst";
+                                cko1_pins_a: cko1@0 {
+                                        cko1 {
+                                                sirf,pins = "cko1grp";
+                                                sirf,function = "cko1";
                                         };
                                 };
                        };
index 43bf3c796cba9cfef5d45032ebcf05b6807dcd4c..0e7fed47bd8d2941292ce8b7411036cf46883f44 100644 (file)
                                        reg = <0x0a>;
                                        VDDA-supply = <&reg_3p3v>;
                                        VDDIO-supply = <&reg_3p3v>;
-
+                                       clocks = <&saif0>;
                                };
 
                                pcf8563: rtc@51 {
index 1f0d38d7b16f5477d2f3b5ec41e6eb78e0f5068b..e035f4664b97493b2261b97b33cfbc97da8b539c 100644 (file)
                                        reg = <0x0a>;
                                        VDDA-supply = <&reg_3p3v>;
                                        VDDIO-supply = <&reg_3p3v>;
-
+                                       clocks = <&saif0>;
                                };
 
                                at24@51 {
index 880df2f13be8d761d679e980e4e756dd9e401d91..44d9da57736e637ef4fcc4a113fcef651a07d58d 100644 (file)
                                        reg = <0x0a>;
                                        VDDA-supply = <&reg_3p3v>;
                                        VDDIO-supply = <&reg_3p3v>;
-
+                                       clocks = <&saif0>;
                                };
 
                                eeprom: eeprom@51 {
index 6a8acb01b1d3ccef1b2a8c82cdacad41bf277f30..9524a05712810bba53382f2b066943cc03c7a675 100644 (file)
                                compatible = "fsl,imx28-saif";
                                reg = <0x80042000 0x2000>;
                                interrupts = <59 80>;
+                               #clock-cells = <0>;
                                clocks = <&clks 53>;
                                dmas = <&dma_apbx 4>;
                                dma-names = "rx-tx";
index 6dd9486c755ba7ac5c3f912a998c978e12602391..ad3471ca17c7aad36904f26b3f0070eac4b58d3a 100644 (file)
                mux-int-port = <2>;
                mux-ext-port = <3>;
        };
+
+       clocks {
+               clk_26M: codec_clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <26000000>;
+                       gpios = <&gpio4 26 1>;
+               };
+       };
 };
 
 &esdhc1 {
                                MX51_PAD_EIM_A27__GPIO2_21   0x5
                                MX51_PAD_CSPI1_SS0__GPIO4_24 0x85
                                MX51_PAD_CSPI1_SS1__GPIO4_25 0x85
+                               MX51_PAD_CSPI1_RDY__GPIO4_26 0x80000000
                        >;
                };
        };
        sgtl5000: codec@0a {
                compatible = "fsl,sgtl5000";
                reg = <0x0a>;
-               clock-frequency = <26000000>;
+               clocks = <&clk_26M>;
                VDDA-supply = <&vdig_reg>;
                VDDIO-supply = <&vvideo_reg>;
        };
index aaa33bc99f78fe6ea3877713482cc35203186868..a630902679410f9a4f356ab430a3199bf3ac852b 100644 (file)
@@ -27,7 +27,7 @@
 
        backlight {
                compatible = "pwm-backlight";
-               pwms = <&pwm2 0 50000 0 0>;
+               pwms = <&pwm2 0 50000>;
                brightness-levels = <0 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100>;
                default-brightness-level = <10>;
                enable-gpios = <&gpio7 7 0>;
index 3895fbba8fce7fff6302f9b30deb72049c24f003..569aa9f2c4eddb90736b47ea20c8a705b31e295b 100644 (file)
                                uart1 {
                                        pinctrl_uart1_1: uart1grp-1 {
                                                fsl,pins = <
-                                                       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1c5
-                                                       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1c5
+                                                       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
+                                                       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
                                                >;
                                        };
 
                                        pinctrl_uart1_2: uart1grp-2 {
                                                fsl,pins = <
-                                                       MX53_PAD_PATA_DIOW__UART1_TXD_MUX  0x1c5
-                                                       MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1c5
+                                                       MX53_PAD_PATA_DIOW__UART1_TXD_MUX  0x1e4
+                                                       MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
                                                >;
                                        };
 
                                uart2 {
                                        pinctrl_uart2_1: uart2grp-1 {
                                                fsl,pins = <
-                                                       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1c5
-                                                       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX     0x1c5
+                                                       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
+                                                       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX     0x1e4
                                                >;
                                        };
 
                                uart3 {
                                        pinctrl_uart3_1: uart3grp-1 {
                                                fsl,pins = <
-                                                       MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1c5
-                                                       MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1c5
-                                                       MX53_PAD_PATA_DA_1__UART3_CTS     0x1c5
-                                                       MX53_PAD_PATA_DA_2__UART3_RTS     0x1c5
+                                                       MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+                                                       MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
+                                                       MX53_PAD_PATA_DA_1__UART3_CTS     0x1e4
+                                                       MX53_PAD_PATA_DA_2__UART3_RTS     0x1e4
                                                >;
                                        };
 
                                        pinctrl_uart3_2: uart3grp-2 {
                                                fsl,pins = <
-                                                       MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1c5
-                                                       MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1c5
+                                                       MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
+                                                       MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
                                                >;
                                        };
 
                                uart4 {
                                        pinctrl_uart4_1: uart4grp-1 {
                                                fsl,pins = <
-                                                       MX53_PAD_KEY_COL0__UART4_TXD_MUX 0x1c5
-                                                       MX53_PAD_KEY_ROW0__UART4_RXD_MUX 0x1c5
+                                                       MX53_PAD_KEY_COL0__UART4_TXD_MUX 0x1e4
+                                                       MX53_PAD_KEY_ROW0__UART4_RXD_MUX 0x1e4
                                                >;
                                        };
                                };
                                uart5 {
                                        pinctrl_uart5_1: uart5grp-1 {
                                                fsl,pins = <
-                                                       MX53_PAD_KEY_COL1__UART5_TXD_MUX 0x1c5
-                                                       MX53_PAD_KEY_ROW1__UART5_RXD_MUX 0x1c5
+                                                       MX53_PAD_KEY_COL1__UART5_TXD_MUX 0x1e4
+                                                       MX53_PAD_KEY_ROW1__UART5_RXD_MUX 0x1e4
                                                >;
                                        };
                                };
index 05e9489cf95c835f4442e90fb47fd3eb92900e79..bbeb623fc2c6f82dc9f92b1c77a90811946f9736 100644 (file)
                                                 sirf,function = "pulse_count";
                                         };
                                 };
-                                cko0_rst_pins_a: cko0_rst@0 {
-                                        cko0_rst {
-                                                sirf,pins = "cko0_rstgrp";
-                                                sirf,function = "cko0_rst";
+                                cko0_pins_a: cko0@0 {
+                                        cko0 {
+                                                sirf,pins = "cko0grp";
+                                                sirf,function = "cko0";
                                         };
                                 };
-                                cko1_rst_pins_a: cko1_rst@0 {
-                                        cko1_rst {
-                                                sirf,pins = "cko1_rstgrp";
-                                                sirf,function = "cko1_rst";
+                                cko1_pins_a: cko1@0 {
+                                        cko1 {
+                                                sirf,pins = "cko1grp";
+                                                sirf,function = "cko1";
                                         };
                                 };
                        };
index 957b21a71b4b7f24267908afe8aae4279eaa3c48..0f246c979262d3c39676576fdde4c2797cb0d118 100644 (file)
                                reg             = <0x9000 0x100>;
                                st,bank-name    = "PIO31";
                        };
+
+                       serial2-oe {
+                               pinctrl_serial2_oe: serial2-1 {
+                                       st,pins {
+                                               output-enable   = <&PIO11 3 ALT2 OUT>;
+                                       };
+                               };
+                       };
+
                };
 
                pin-controller-rear {
                                        st,pins {
                                                tx      = <&PIO17 4 ALT2 OUT>;
                                                rx      = <&PIO17 5 ALT2 IN>;
-                                               output-enable   = <&PIO11 3 ALT2 OUT>;
                                        };
                                };
                        };
index 3cecd9689a4999927d60aeb1f320dafed99d0965..1a0326ea7d070ad762d6f83719aa0fcc29a98dd2 100644 (file)
@@ -79,7 +79,7 @@
                        interrupts      = <0 197 0>;
                        clocks          = <&CLK_S_ICN_REG_0>;
                        pinctrl-names   = "default";
-                       pinctrl-0       = <&pinctrl_serial2>;
+                       pinctrl-0       = <&pinctrl_serial2 &pinctrl_serial2_oe>;
                };
 
                /* SBC_UART1 */
index b3034da00a37bfe6a5361420bc2fb8d99101fb5a..ae6a17aed9ee224c85498b2bc6b1e0fa43e75e56 100644 (file)
                regulator-max-microvolt = <3150000>;
        };
 
+       vmmc2: regulator-vmmc2 {
+               compatible = "ti,twl4030-vmmc2";
+               regulator-min-microvolt = <1850000>;
+               regulator-max-microvolt = <3150000>;
+       };
+
        vusb1v5: regulator-vusb1v5 {
                compatible = "ti,twl4030-vusb1v5";
        };
index e1eb7dadda80a56255c63d1a646885f41115d6e0..67d929cf98045235a1a39eeeb7c884c2b2bccddc 100644 (file)
                                compatible = "fsl,mvf600-fec";
                                reg = <0x400d0000 0x1000>;
                                interrupts = <0 78 0x04>;
-                               clocks = <&clks VF610_CLK_ENET>,
-                                       <&clks VF610_CLK_ENET>,
+                               clocks = <&clks VF610_CLK_ENET0>,
+                                       <&clks VF610_CLK_ENET0>,
                                        <&clks VF610_CLK_ENET>;
                                clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
                                compatible = "fsl,mvf600-fec";
                                reg = <0x400d1000 0x1000>;
                                interrupts = <0 79 0x04>;
-                               clocks = <&clks VF610_CLK_ENET>,
-                                       <&clks VF610_CLK_ENET>,
+                               clocks = <&clks VF610_CLK_ENET1>,
+                                       <&clks VF610_CLK_ENET1>,
                                        <&clks VF610_CLK_ENET>;
                                clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
index a432e6c1dac18fdf33d1b5d85bfb6c1b7e6cfed0..39ad030ac0c72b529b9cf3166a003b9feaa1f879 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/edma.h>
-#include <linux/err.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_dma.h>
index 7c868139bdb0dd42e9b97d34b794d6cabe83dc64..1571bea48bed12b6702ea9d1e09deb7cffb803cf 100644 (file)
@@ -102,6 +102,8 @@ CONFIG_SND_SOC=m
 CONFIG_SND_DAVINCI_SOC=m
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_DMADEVICES=y
+CONFIG_TI_EDMA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
index c86fd75e181ab003df201b1966f22594c2d24013..ab2f7378352c7e1861bac50cf4a21527a7d9564c 100644 (file)
@@ -162,6 +162,8 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_TI_EDMA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
index fe0bdc361d2c2fea4ebf5a274415683e07445d1a..6e572c64cf5a1258008232a002301ab7925b0911 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_OMAP_OCP2SCP=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI_PLATFORM=y
@@ -61,6 +62,7 @@ CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_KS8851=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=y
 CONFIG_MDIO_SUN4I=y
@@ -89,6 +91,7 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_I2C_SIRF=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_SIRF=y
 CONFIG_SPI_TEGRA114=y
@@ -111,11 +114,12 @@ CONFIG_FB_SIMPLE=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_EHCI_TEGRA=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_ISP1760_HCD=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_AB8500_USB=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_OMAP_USB2=y
index 35f8cf299fa2186f0f27ab42470dbd582f55d6f6..263ae3869e32c5f9ecf8bc2f2fd63b8ce8291eda 100644 (file)
@@ -1,6 +1,8 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -48,7 +50,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_TESTS=m
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND_ECC_SMC=y
 CONFIG_MTD_NAND=y
@@ -94,8 +95,10 @@ CONFIG_I2C_GPIO=y
 CONFIG_I2C_NOMADIK=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
 CONFIG_MMC=y
-CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
index afbc439f11d4fba53bd3882535eda6b41540fe2f..4cdb61c5445943d7aa2e9a50b23c151b0ecf6a9c 100644 (file)
@@ -505,7 +505,7 @@ static struct vpbe_output dm365evm_vpbe_outputs[] = {
 /*
  * Amplifiers on the board
  */
-struct ths7303_platform_data ths7303_pdata = {
+static struct ths7303_platform_data ths7303_pdata = {
        .ch_1 = 3,
        .ch_2 = 3,
        .ch_3 = 3,
index 42ef53f62c6ce44344a42ac49b71f2b8e34f6ecf..86100d17969473112cbea30c4b3d3a1113420eee 100644 (file)
@@ -860,7 +860,7 @@ static struct platform_device dm355_vpbe_display = {
        },
 };
 
-struct venc_platform_data dm355_venc_pdata = {
+static struct venc_platform_data dm355_venc_pdata = {
        .setup_pinmux   = dm355_vpbe_setup_pinmux,
        .setup_clock    = dm355_venc_setup_clock,
 };
index fa7af5eda52d1bcf17a6120e3a603251e2b6de7f..dad28029ba9bee623ccbc0c29efb0a773453b388 100644 (file)
@@ -1349,7 +1349,7 @@ static struct platform_device dm365_vpbe_display = {
        },
 };
 
-struct venc_platform_data dm365_venc_pdata = {
+static struct venc_platform_data dm365_venc_pdata = {
        .setup_pinmux   = dm365_vpbe_setup_pinmux,
        .setup_clock    = dm365_venc_setup_clock,
 };
index 855d4a7b462d12fd0fc67b4abd3a55b0b0522530..5952e68c76c40e622e828a9e1849542b69f12aad 100644 (file)
@@ -92,6 +92,7 @@ config SOC_EXYNOS5440
        bool "SAMSUNG EXYNOS5440"
        default y
        depends on ARCH_EXYNOS5
+       select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
        select ARCH_HAS_OPP
        select HAVE_ARM_ARCH_TIMER
        select AUTO_ZRELADDR
index e970a7a4e278c137f6dffc358811f55cfea1c45d..53696154aead3da032d710720cd45ca72e634827 100644 (file)
@@ -14,7 +14,7 @@ obj-                          :=
 
 obj-$(CONFIG_ARCH_EXYNOS)      += common.o
 
-obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_S5P_PM)           += pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
 obj-$(CONFIG_CPU_IDLE)         += cpuidle.o
 
index 164685bd25c82ec0f01f1eaeb39f36a125fd4738..ba95e5db25011a0801c2ef1f7c27270b713280ee 100644 (file)
@@ -58,7 +58,6 @@ static const char name_exynos5440[] = "EXYNOS5440";
 
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
-static void exynos5440_map_io(void);
 static int exynos_init(void);
 
 static struct cpu_table cpu_ids[] __initdata = {
@@ -95,7 +94,6 @@ static struct cpu_table cpu_ids[] __initdata = {
        }, {
                .idcode         = EXYNOS5440_SOC_ID,
                .idmask         = EXYNOS5_SOC_MASK,
-               .map_io         = exynos5440_map_io,
                .init           = exynos_init,
                .name           = name_exynos5440,
        },
@@ -149,11 +147,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_UART,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_UART),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_CMU,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_CMU),
@@ -268,20 +261,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS5_PA_PMU),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_UART,
-               .pfn            = __phys_to_pfn(EXYNOS5_PA_UART),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc exynos5440_iodesc0[] __initdata = {
-       {
-               .virtual        = (unsigned long)S3C_VA_UART,
-               .pfn            = __phys_to_pfn(EXYNOS5440_PA_UART0),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
        },
 };
 
@@ -388,11 +367,6 @@ static void __init exynos5_map_io(void)
                iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
 }
 
-static void __init exynos5440_map_io(void)
-{
-       iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0));
-}
-
 void __init exynos_init_time(void)
 {
        of_clk_init(NULL);
index 3e156bcddcb4cc65586ab652c7de52b60d47208f..972490fc09d627241a1d3c63e7d234693b4f03d8 100644 (file)
@@ -97,6 +97,5 @@ struct exynos_pmu_conf {
 };
 
 extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
-extern void s3c_cpu_resume(void);
 
 #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
index 17a18ff3d71e289df9909cb3976d6e414c768dff..225ee8431c7282d1301d17c255687189482e7042 100644 (file)
@@ -25,6 +25,7 @@
 #include <mach/regs-pmu.h>
 
 #include <plat/cpu.h>
+#include <plat/pm.h>
 
 #include "common.h"
 
index 374ef2cf7152c366fe56388909f751dac4d658c0..2a4cdb7cb326a400060fd9c959042145dedb17c2 100644 (file)
 
 #define PLAT_PHYS_OFFSET               UL(0x40000000)
 
+#ifndef CONFIG_ARM_LPAE
 /* Maximum of 256MiB in one bank */
 #define MAX_PHYSMEM_BITS       32
 #define SECTION_SIZE_BITS      28
+#else
+#define MAX_PHYSMEM_BITS       36
+#define SECTION_SIZE_BITS      31
+#endif
 
 #endif /* __ASM_ARCH_MEMORY_H */
index 41c20692a13f0f189c1acaf011831048b6944a0a..c679db57726934de2f0338fadbbda0be05e49e74 100644 (file)
@@ -217,6 +217,9 @@ static __init int exynos_pm_drvinit(void)
        struct clk *pll_base;
        unsigned int tmp;
 
+       if (soc_is_exynos5440())
+               return 0;
+
        s3c_pm_init();
 
        /* All wakeup disable */
@@ -340,6 +343,9 @@ static struct syscore_ops exynos_pm_syscore_ops = {
 
 static __init int exynos_pm_syscore_init(void)
 {
+       if (soc_is_exynos5440())
+               return 0;
+
        register_syscore_ops(&exynos_pm_syscore_ops);
        return 0;
 }
index a7cd2cf5e08de32c2ceafc508559d3201919dcc4..3490a24f969e4a0b450ef146cee72f37e1cb6c9f 100644 (file)
@@ -276,8 +276,6 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
 
        sys->mem_offset  = DC21285_PCI_MEM;
 
-       pci_ioremap_io(0, DC21285_PCI_IO);
-
        pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
        pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
 
index dc5d6becd8c7c13f54406eaebead83bf11ffd9d2..88815795fe2678f7c41e54fd296397ace8de9a62 100644 (file)
@@ -115,6 +115,7 @@ static int highbank_platform_notifier(struct notifier_block *nb,
 {
        struct resource *res;
        int reg = -1;
+       u32 val;
        struct device *dev = __dev;
 
        if (event != BUS_NOTIFY_ADD_DEVICE)
@@ -141,10 +142,10 @@ static int highbank_platform_notifier(struct notifier_block *nb,
                return NOTIFY_DONE;
 
        if (of_property_read_bool(dev->of_node, "dma-coherent")) {
-               writel(0xff31, sregs_base + reg);
+               val = readl(sregs_base + reg);
+               writel(val | 0xff01, sregs_base + reg);
                set_dma_ops(dev, &arm_coherent_dma_ops);
-       } else
-               writel(0, sregs_base + reg);
+       }
 
        return NOTIFY_OK;
 }
index 4282e99f5ca1803254a44449aee835c653429c6b..86567d980b0743df9eadf44bfac489bc01634b9d 100644 (file)
@@ -199,7 +199,8 @@ static const char *pcie_axi_sels[]  = { "axi", "ahb", };
 static const char *ssi_sels[]          = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", };
 static const char *usdhc_sels[]        = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
-static const char *emi_sels[]          = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *emi_sels[]          = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
+static const char *emi_slow_sels[]      = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *vdo_axi_sels[]      = { "axi", "ahb", };
 static const char *vpu_axi_sels[]      = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
@@ -392,7 +393,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[usdhc4_sel]       = imx_clk_mux("usdhc4_sel",       base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels));
        clk[enfc_sel]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
        clk[emi_sel]          = imx_clk_mux("emi_sel",          base + 0x1c, 27, 2, emi_sels,          ARRAY_SIZE(emi_sels));
-       clk[emi_slow_sel]     = imx_clk_mux("emi_slow_sel",     base + 0x1c, 29, 2, emi_sels,          ARRAY_SIZE(emi_sels));
+       clk[emi_slow_sel]     = imx_clk_mux("emi_slow_sel",     base + 0x1c, 29, 2, emi_slow_sels,     ARRAY_SIZE(emi_slow_sels));
        clk[vdo_axi_sel]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
        clk[vpu_axi_sel]      = imx_clk_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
        clk[cko1_sel]         = imx_clk_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
index d617c0b7c8095f23c3273c86aadd5421ad0d29d0..b169a396d93bfcf193c83d7329a6fdc290101425 100644 (file)
@@ -183,6 +183,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel", CCM_CSCMR2, 0, 3, enet_ts_sels, 7);
        clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel", CCM_CSCDR1, 24);
        clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel", CCM_CSCDR1, 23);
+       clk[VF610_CLK_ENET0] = imx_clk_gate2("enet0", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(0));
+       clk[VF610_CLK_ENET1] = imx_clk_gate2("enet1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(1));
 
        clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7));
 
index e074616d54ca5e034e0b6331b8235c7a72971a37..8a65f192e7f31fb82b998b9e094ae9e1f69441a7 100644 (file)
 #define MX27_INT_GPT4          (NR_IRQS_LEGACY + 4)
 #define MX27_INT_RTIC          (NR_IRQS_LEGACY + 5)
 #define MX27_INT_CSPI3         (NR_IRQS_LEGACY + 6)
-#define MX27_INT_SDHC          (NR_IRQS_LEGACY + 7)
+#define MX27_INT_MSHC          (NR_IRQS_LEGACY + 7)
 #define MX27_INT_GPIO          (NR_IRQS_LEGACY + 8)
 #define MX27_INT_SDHC3         (NR_IRQS_LEGACY + 9)
 #define MX27_INT_SDHC2         (NR_IRQS_LEGACY + 10)
index fe4d9ff93a7ef8560cd6948aaa99720242df5865..b661c5c2870a88d09a76b51d7166650a693250ac 100644 (file)
@@ -49,7 +49,7 @@ static const char *keystone_match[] __initconst = {
        NULL,
 };
 
-void keystone_restart(char mode, const char *cmd)
+void keystone_restart(enum reboot_mode mode, const char *cmd)
 {
        u32 val;
 
index 627fa7e41fbabbeccf38c1703dc26ed2a98d66db..3eed0006d189c0c0e88412485dba67e1800b2d6e 100644 (file)
@@ -62,7 +62,7 @@ config SOC_OMAP5
        select HAVE_SMP
        select COMMON_CLK
        select HAVE_ARM_ARCH_TIMER
-       select ARM_ERRATA_798181
+       select ARM_ERRATA_798181 if SMP
 
 config SOC_AM33XX
        bool "AM33XX support"
index e5fbfed69aa2bc5094b508a3219c8988d0d3dbe7..be5d005ebad2866ea7432586beba45e000330be9 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/irqdomain.h>
+#include <linux/clk.h>
 
 #include <asm/mach/arch.h>
 
@@ -35,6 +36,21 @@ static struct of_device_id omap_dt_match_table[] __initdata = {
        { }
 };
 
+/*
+ * Create alias for USB host PHY clock.
+ * Remove this when clock phandle can be provided via DT
+ */
+static void __init legacy_init_ehci_clk(char *clkname)
+{
+       int ret;
+
+       ret = clk_add_alias("main_clk", NULL, clkname, NULL);
+       if (ret) {
+               pr_err("%s:Failed to add main_clk alias to %s :%d\n",
+                                               __func__, clkname, ret);
+       }
+}
+
 static void __init omap_generic_init(void)
 {
        omap_sdrc_init(NULL, NULL);
@@ -45,10 +61,15 @@ static void __init omap_generic_init(void)
         * HACK: call display setup code for selected boards to enable omapdss.
         * This will be removed when omapdss supports DT.
         */
-       if (of_machine_is_compatible("ti,omap4-panda"))
+       if (of_machine_is_compatible("ti,omap4-panda")) {
                omap4_panda_display_init_of();
+               legacy_init_ehci_clk("auxclk3_ck");
+
+       }
        else if (of_machine_is_compatible("ti,omap4-sdp"))
                omap_4430sdp_display_init_of();
+       else if (of_machine_is_compatible("ti,omap5-uevm"))
+               legacy_init_ehci_clk("auxclk1_ck");
 }
 
 #ifdef CONFIG_SOC_OMAP2420
index f6726bb4eb954bf1cdaf073b4940269137673916..3a3362fa793edd06e2dab0f4d88d08c8a1af4d0f 100644 (file)
@@ -477,16 +477,24 @@ static int em_x270_usb_hub_init(void)
        /* USB Hub power-on and reset */
        gpio_direction_output(usb_hub_reset, 1);
        gpio_direction_output(GPIO9_USB_VBUS_EN, 0);
-       regulator_enable(em_x270_usb_ldo);
+       err = regulator_enable(em_x270_usb_ldo);
+       if (err)
+               goto err_free_rst_gpio;
+
        gpio_set_value(usb_hub_reset, 0);
        gpio_set_value(usb_hub_reset, 1);
        regulator_disable(em_x270_usb_ldo);
-       regulator_enable(em_x270_usb_ldo);
+       err = regulator_enable(em_x270_usb_ldo);
+       if (err)
+               goto err_free_rst_gpio;
+
        gpio_set_value(usb_hub_reset, 0);
        gpio_set_value(GPIO9_USB_VBUS_EN, 1);
 
        return 0;
 
+err_free_rst_gpio:
+       gpio_free(usb_hub_reset);
 err_free_vbus_gpio:
        gpio_free(GPIO9_USB_VBUS_EN);
 err_free_usb_ldo:
@@ -592,7 +600,7 @@ err_irq:
        return err;
 }
 
-static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
+static int em_x270_mci_setpower(struct device *dev, unsigned int vdd)
 {
        struct pxamci_platform_data* p_d = dev->platform_data;
 
@@ -600,10 +608,11 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
                int vdd_uV = (2000 + (vdd - __ffs(MMC_VDD_20_21)) * 100) * 1000;
 
                regulator_set_voltage(em_x270_sdio_ldo, vdd_uV, vdd_uV);
-               regulator_enable(em_x270_sdio_ldo);
+               return regulator_enable(em_x270_sdio_ldo);
        } else {
                regulator_disable(em_x270_sdio_ldo);
        }
+       return 0;
 }
 
 static void em_x270_mci_exit(struct device *dev, void *data)
index d2c6523183764c2e809076bca2fc527826a209b1..dd70343c87085edf4da384fedd434a339802756c 100644 (file)
@@ -408,7 +408,7 @@ static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_in
        return err;
 }
 
-static void mainstone_mci_setpower(struct device *dev, unsigned int vdd)
+static int mainstone_mci_setpower(struct device *dev, unsigned int vdd)
 {
        struct pxamci_platform_data* p_d = dev->platform_data;
 
@@ -420,6 +420,7 @@ static void mainstone_mci_setpower(struct device *dev, unsigned int vdd)
                printk(KERN_DEBUG "%s: off\n", __func__);
                MST_MSCWR1 &= ~MST_MSCWR1_MMC_ON;
        }
+       return 0;
 }
 
 static void mainstone_mci_exit(struct device *dev, void *data)
index fb7f1d1627dc1d11863ae4bcaeeabb0bccda4524..13e5b00eae900beb689a2c0293be84600913a890 100644 (file)
@@ -335,7 +335,7 @@ static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
        return err;
 }
 
-static void pcm990_mci_setpower(struct device *dev, unsigned int vdd)
+static int pcm990_mci_setpower(struct device *dev, unsigned int vdd)
 {
        struct pxamci_platform_data *p_d = dev->platform_data;
        u8 val;
@@ -348,6 +348,7 @@ static void pcm990_mci_setpower(struct device *dev, unsigned int vdd)
                val &= ~PCM990_CTRL_MMC2PWR;
 
        pcm990_cpld_writeb(PCM990_CTRL_MMC2PWR, PCM990_CTRL_REG5);
+       return 0;
 }
 
 static void pcm990_mci_exit(struct device *dev, void *data)
index 711d37e26bd8111b1b4821c849b96394cc4f102b..aedf053a1de5ccac5f3505c93f802ef6dadbe50a 100644 (file)
@@ -258,7 +258,7 @@ err_free_2:
        return err;
 }
 
-static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
+static int poodle_mci_setpower(struct device *dev, unsigned int vdd)
 {
        struct pxamci_platform_data* p_d = dev->platform_data;
 
@@ -270,6 +270,8 @@ static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
                gpio_set_value(POODLE_GPIO_SD_PWR1, 0);
                gpio_set_value(POODLE_GPIO_SD_PWR, 0);
        }
+
+       return 0;
 }
 
 static void poodle_mci_exit(struct device *dev, void *data)
index 2125df0444e7be24f7aa1e3c6ce153fe0b78655c..4c29173026e8e67ff6ec0409f1862e205e5ffc4c 100644 (file)
@@ -598,7 +598,7 @@ static inline void spitz_spi_init(void) {}
  * NOTE: The card detect interrupt isn't debounced so we delay it by 250ms to
  * give the card a chance to fully insert/eject.
  */
-static void spitz_mci_setpower(struct device *dev, unsigned int vdd)
+static int spitz_mci_setpower(struct device *dev, unsigned int vdd)
 {
        struct pxamci_platform_data* p_d = dev->platform_data;
 
@@ -606,6 +606,8 @@ static void spitz_mci_setpower(struct device *dev, unsigned int vdd)
                spitz_card_pwr_ctrl(SCOOP_CPR_SD_3V, SCOOP_CPR_SD_3V);
        else
                spitz_card_pwr_ctrl(SCOOP_CPR_SD_3V, 0x0);
+
+       return 0;
 }
 
 static struct pxamci_platform_data spitz_mci_platform_data = {
index 88fde43c948c740a1bccd8f2520d4d3a8dc63f98..62aea3e835f315266ba887367310ec249503cd21 100644 (file)
@@ -734,9 +734,10 @@ static int stargate2_mci_init(struct device *dev,
  *
  * Very simple control. Either it is on or off and is controlled by
  * a gpio pin */
-static void stargate2_mci_setpower(struct device *dev, unsigned int vdd)
+static int stargate2_mci_setpower(struct device *dev, unsigned int vdd)
 {
        gpio_set_value(SG2_SD_POWER_ENABLE, !!vdd);
+       return 0;
 }
 
 static void stargate2_mci_exit(struct device *dev, void *data)
index 34fffdf6fc1dc4b7f699418976e0b3d943c512a6..564553694b543d24df4eca3fa6a305c59520ce79 100644 (file)
@@ -119,66 +119,101 @@ static struct clk init_clocks_off[] = {
        }
 };
 
-static struct clk init_clocks[] = {
-       {
-               .name           = "lcd",
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_LCDC,
-       }, {
-               .name           = "gpio",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_GPIO,
-       }, {
-               .name           = "usb-host",
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_USBH,
-       }, {
-               .name           = "usb-device",
-               .parent         = &clk_h,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_USBD,
-       }, {
-               .name           = "timers",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_PWMT,
-       }, {
-               .name           = "uart",
-               .devname        = "s3c2410-uart.0",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART0,
-       }, {
-               .name           = "uart",
-               .devname        = "s3c2410-uart.1",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART1,
-       }, {
-               .name           = "uart",
-               .devname        = "s3c2410-uart.2",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_UART2,
-       }, {
-               .name           = "rtc",
-               .parent         = &clk_p,
-               .enable         = s3c2410_clkcon_enable,
-               .ctrlbit        = S3C2410_CLKCON_RTC,
-       }, {
-               .name           = "watchdog",
-               .parent         = &clk_p,
-               .ctrlbit        = 0,
-       }, {
-               .name           = "usb-bus-host",
-               .parent         = &clk_usb_bus,
-       }, {
-               .name           = "usb-bus-gadget",
-               .parent         = &clk_usb_bus,
-       },
+static struct clk clk_lcd = {
+       .name           = "lcd",
+       .parent         = &clk_h,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_LCDC,
+};
+
+static struct clk clk_gpio = {
+       .name           = "gpio",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_GPIO,
+};
+
+static struct clk clk_usb_host = {
+       .name           = "usb-host",
+       .parent         = &clk_h,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_USBH,
+};
+
+static struct clk clk_usb_device = {
+       .name           = "usb-device",
+       .parent         = &clk_h,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_USBD,
+};
+
+static struct clk clk_timers = {
+       .name           = "timers",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_PWMT,
+};
+
+struct clk s3c24xx_clk_uart0 = {
+       .name           = "uart",
+       .devname        = "s3c2410-uart.0",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_UART0,
+};
+
+struct clk s3c24xx_clk_uart1 = {
+       .name           = "uart",
+       .devname        = "s3c2410-uart.1",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_UART1,
+};
+
+struct clk s3c24xx_clk_uart2 = {
+       .name           = "uart",
+       .devname        = "s3c2410-uart.2",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_UART2,
+};
+
+static struct clk clk_rtc = {
+       .name           = "rtc",
+       .parent         = &clk_p,
+       .enable         = s3c2410_clkcon_enable,
+       .ctrlbit        = S3C2410_CLKCON_RTC,
+};
+
+static struct clk clk_watchdog = {
+       .name           = "watchdog",
+       .parent         = &clk_p,
+       .ctrlbit        = 0,
+};
+
+static struct clk clk_usb_bus_host = {
+       .name           = "usb-bus-host",
+       .parent         = &clk_usb_bus,
+};
+
+static struct clk clk_usb_bus_gadget = {
+       .name           = "usb-bus-gadget",
+       .parent         = &clk_usb_bus,
+};
+
+static struct clk *init_clocks[] = {
+       &clk_lcd,
+       &clk_gpio,
+       &clk_usb_host,
+       &clk_usb_device,
+       &clk_timers,
+       &s3c24xx_clk_uart0,
+       &s3c24xx_clk_uart1,
+       &s3c24xx_clk_uart2,
+       &clk_rtc,
+       &clk_watchdog,
+       &clk_usb_bus_host,
+       &clk_usb_bus_gadget,
 };
 
 /* s3c2410_baseclk_add()
@@ -195,7 +230,6 @@ int __init s3c2410_baseclk_add(void)
 {
        unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
        unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-       struct clk *clkp;
        struct clk *xtal;
        int ret;
        int ptr;
@@ -207,8 +241,9 @@ int __init s3c2410_baseclk_add(void)
 
        /* register clocks from clock array */
 
-       clkp = init_clocks;
-       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++) {
+               struct clk *clkp = init_clocks[ptr];
+
                /* ensure that we note the clock state */
 
                clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
index 1069b56808265b5efaf9877b9ed6a1b7dc5ea833..aaf006d1d6dc9ec6111ae080e3e4f15350615561 100644 (file)
@@ -166,6 +166,9 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
+       CLKDEV_INIT("s3c2440-uart.0", "uart", &s3c24xx_clk_uart0),
+       CLKDEV_INIT("s3c2440-uart.1", "uart", &s3c24xx_clk_uart1),
+       CLKDEV_INIT("s3c2440-uart.2", "uart", &s3c24xx_clk_uart2),
        CLKDEV_INIT("s3c2440-camif", "camera", &s3c2440_clk_cam_upll),
 };
 
index d04e3bfe19189082823e4a74c60d1de1de9eed7f..835833e3c4f8fb193f6d177c88ef35199488b33f 100644 (file)
@@ -11,8 +11,9 @@ menuconfig ARCH_STI
        select HAVE_SMP
        select HAVE_ARM_SCU if SMP
        select ARCH_REQUIRE_GPIOLIB
-       select ARM_ERRATA_720789
        select ARM_ERRATA_754322
+       select ARM_ERRATA_764369
+       select ARM_ERRATA_775420
        select PL310_ERRATA_753970 if CACHE_PL310
        select PL310_ERRATA_769419 if CACHE_PL310
        help
index 5b799c29886e544778d115a0e7570f3f100875ad..5f252569c68987d908546b55bb921d5f7693c7af 100644 (file)
@@ -91,7 +91,7 @@ static void __init zynq_map_io(void)
        zynq_scu_map_io();
 }
 
-static void zynq_system_reset(char mode, const char *cmd)
+static void zynq_system_reset(enum reboot_mode mode, const char *cmd)
 {
        zynq_slcr_system_reset();
 }
index 3dc5cbea86cc9cc838d5b864f0eabaed76777e23..a5b5ff6e68d2015e4080112c821fb6d0ac0bf3d6 100644 (file)
@@ -29,6 +29,13 @@ config PLAT_S5P
        help
          Base platform code for Samsung's S5P series SoC.
 
+config SAMSUNG_PM
+       bool
+       depends on PM && (PLAT_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || S5P_PM)
+       default y
+       help
+         Base platform power management code for samsung code
+
 if PLAT_SAMSUNG
 
 # boot configurations
index 98d07d8fc7a71ffa869fa397cc8f74977264f17c..199bbe304d02f1e70838c0f012a73e7688655436 100644 (file)
@@ -51,7 +51,7 @@ obj-$(CONFIG_SAMSUNG_DMADEV)  += dma-ops.o
 
 # PM support
 
-obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_SAMSUNG_PM)       += pm.o
 obj-$(CONFIG_SAMSUNG_PM_GPIO)  += pm-gpio.o
 obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o
 
index a62753dc15baf144ecfc2ea7efe53bfc6f13a9fe..df45d6edc98d9e723242f3890e1ea4df124d8888 100644 (file)
@@ -83,6 +83,11 @@ extern struct clk clk_ext;
 extern struct clksrc_clk clk_epllref;
 extern struct clksrc_clk clk_esysclk;
 
+/* S3C24XX UART clocks */
+extern struct clk s3c24xx_clk_uart0;
+extern struct clk s3c24xx_clk_uart1;
+extern struct clk s3c24xx_clk_uart2;
+
 /* S3C64XX specific clocks */
 extern struct clk clk_h2;
 extern struct clk clk_27m;
index 5d47ca35cabde40cfa56ae05344a275909ac9e72..6bc1a8f471e391e127be0dd7cfadf0eefa33a0f2 100644 (file)
@@ -19,7 +19,7 @@
 
 struct device;
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_SAMSUNG_PM
 
 extern __init int s3c_pm_init(void);
 extern __init int s3c64xx_pm_init(void);
@@ -58,8 +58,6 @@ extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
 
 /* from sleep.S */
 
-extern void s3c_cpu_resume(void);
-
 extern int s3c2410_cpu_suspend(unsigned long);
 
 /* sleep save info */
@@ -106,12 +104,14 @@ extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
 extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
 extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_SAMSUNG_PM
 extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
 extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
+extern void s3c_cpu_resume(void);
 #else
 #define s3c_irq_wake NULL
 #define s3c_irqext_wake NULL
+#define s3c_cpu_resume NULL
 #endif
 
 /* PM debug functions */
index ea36136424511b4d3c7518b0e839897e266f7137..d0c23010b693a57625d002694528d0cd2fffaaa5 100644 (file)
@@ -80,7 +80,7 @@ unsigned char pm_uart_udivslot;
 
 #ifdef CONFIG_SAMSUNG_PM_DEBUG
 
-static struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
+static struct pm_uart_save uart_save;
 
 static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
 {
@@ -101,11 +101,7 @@ static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
 
 static void s3c_pm_save_uarts(void)
 {
-       struct pm_uart_save *save = uart_save;
-       unsigned int uart;
-
-       for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-               s3c_pm_save_uart(uart, save);
+       s3c_pm_save_uart(CONFIG_DEBUG_S3C_UART, &uart_save);
 }
 
 static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
@@ -126,11 +122,7 @@ static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
 
 static void s3c_pm_restore_uarts(void)
 {
-       struct pm_uart_save *save = uart_save;
-       unsigned int uart;
-
-       for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-               s3c_pm_restore_uart(uart, save);
+       s3c_pm_restore_uart(CONFIG_DEBUG_S3C_UART, &uart_save);
 }
 #else
 static void s3c_pm_save_uarts(void) { }
index 3659e460071ddfb1f84715ff7736c97ef9f9bb20..23a3c4791d86cb71f9a2520e2176212b1e107503 100644 (file)
 #include <linux/compiler.h>
 
 #ifndef CONFIG_ARM64_64K_PAGES
-#define THREAD_SIZE_ORDER      1
+#define THREAD_SIZE_ORDER      2
 #endif
 
-#define THREAD_SIZE            8192
+#define THREAD_SIZE            16384
 #define THREAD_START_SP                (THREAD_SIZE - 16)
 
 #ifndef __ASSEMBLY__
index 439827271e3d5bfada26390c9a226bbf6ec763e5..26e310c5434446c7bfc0a9a3f9b443139ffa3368 100644 (file)
@@ -21,6 +21,7 @@
 #define BOOT_CPU_MODE_EL2      (0x0e12b007)
 
 #ifndef __ASSEMBLY__
+#include <asm/cacheflush.h>
 
 /*
  * __boot_cpu_mode records what mode CPUs were booted in.
@@ -36,9 +37,20 @@ extern u32 __boot_cpu_mode[2];
 void __hyp_set_vectors(phys_addr_t phys_vector_base);
 phys_addr_t __hyp_get_vectors(void);
 
+static inline void sync_boot_mode(void)
+{
+       /*
+        * As secondaries write to __boot_cpu_mode with caches disabled, we
+        * must flush the corresponding cache entries to ensure the visibility
+        * of their writes.
+        */
+       __flush_dcache_area(__boot_cpu_mode, sizeof(__boot_cpu_mode));
+}
+
 /* Reports the availability of HYP mode */
 static inline bool is_hyp_mode_available(void)
 {
+       sync_boot_mode();
        return (__boot_cpu_mode[0] == BOOT_CPU_MODE_EL2 &&
                __boot_cpu_mode[1] == BOOT_CPU_MODE_EL2);
 }
@@ -46,6 +58,7 @@ static inline bool is_hyp_mode_available(void)
 /* Check if the bootloader has booted CPUs in different modes */
 static inline bool is_hyp_mode_mismatched(void)
 {
+       sync_boot_mode();
        return __boot_cpu_mode[0] != __boot_cpu_mode[1];
 }
 
index 1d1314280a03a678c4ef63092712d49079386cdd..6ad781b21c080a50c4c061dbd4037beafe8ba09b 100644 (file)
 
        .macro  get_thread_info, rd
        mov     \rd, sp
-       and     \rd, \rd, #~((1 << 13) - 1)     // top of 8K stack
+       and     \rd, \rd, #~(THREAD_SIZE - 1)   // top of stack
        .endm
 
 /*
index 1788bf6b471f63a6fe708cb608039c51fe1e40fa..57fb55c44c901c19c7264f02ff44d6c481fadc56 100644 (file)
@@ -81,7 +81,7 @@ void soft_restart(unsigned long addr)
 void (*pm_power_off)(void);
 EXPORT_SYMBOL_GPL(pm_power_off);
 
-void (*arm_pm_restart)(char str, const char *cmd);
+void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
 EXPORT_SYMBOL_GPL(arm_pm_restart);
 
 void arch_cpu_idle_prepare(void)
index 09a8743143f37a046e8d57e3d65f58f9a1bd3cb4..d3e5e9bc8f946fa3fd7158a3ecc931561c71c1a3 100644 (file)
@@ -55,6 +55,8 @@ struct device_node;
 #define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
 #define EEH_PE_PHB_DEAD                (1 << 2)        /* Dead PHB             */
 
+#define EEH_PE_KEEP            (1 << 8)        /* Keep PE on hotplug   */
+
 struct eeh_pe {
        int type;                       /* PE type: PHB/Bus/Device      */
        int state;                      /* PE EEH dependent mode        */
@@ -72,8 +74,8 @@ struct eeh_pe {
        struct list_head child;         /* Child PEs                    */
 };
 
-#define eeh_pe_for_each_dev(pe, edev) \
-               list_for_each_entry(edev, &pe->edevs, list)
+#define eeh_pe_for_each_dev(pe, edev, tmp) \
+               list_for_each_entry_safe(edev, tmp, &pe->edevs, list)
 
 /*
  * The struct is used to trace EEH state for the associated
@@ -82,7 +84,13 @@ struct eeh_pe {
  * another tree except the currently existing tree of PCI
  * buses and PCI devices
  */
-#define EEH_DEV_IRQ_DISABLED   (1<<0)  /* Interrupt disabled           */
+#define EEH_DEV_BRIDGE         (1 << 0)        /* PCI bridge           */
+#define EEH_DEV_ROOT_PORT      (1 << 1)        /* PCIe root port       */
+#define EEH_DEV_DS_PORT                (1 << 2)        /* Downstream port      */
+#define EEH_DEV_IRQ_DISABLED   (1 << 3)        /* Interrupt disabled   */
+#define EEH_DEV_DISCONNECTED   (1 << 4)        /* Removing from PE     */
+
+#define EEH_DEV_SYSFS          (1 << 8)        /* Sysfs created        */
 
 struct eeh_dev {
        int mode;                       /* EEH mode                     */
@@ -90,11 +98,13 @@ struct eeh_dev {
        int config_addr;                /* Config address               */
        int pe_config_addr;             /* PE config address            */
        u32 config_space[16];           /* Saved PCI config space       */
+       u8 pcie_cap;                    /* Saved PCIe capability        */
        struct eeh_pe *pe;              /* Associated PE                */
        struct list_head list;          /* Form link list in the PE     */
        struct pci_controller *phb;     /* Associated PHB               */
        struct device_node *dn;         /* Associated device node       */
        struct pci_dev *pdev;           /* Associated PCI device        */
+       struct pci_bus *bus;            /* PCI bus for partial hotplug  */
 };
 
 static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev)
@@ -193,8 +203,10 @@ int eeh_phb_pe_create(struct pci_controller *phb);
 struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb);
 struct eeh_pe *eeh_pe_get(struct eeh_dev *edev);
 int eeh_add_to_parent_pe(struct eeh_dev *edev);
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe);
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev);
 void eeh_pe_update_time_stamp(struct eeh_pe *pe);
+void *eeh_pe_traverse(struct eeh_pe *root,
+               eeh_traverse_func fn, void *flag);
 void *eeh_pe_dev_traverse(struct eeh_pe *root,
                eeh_traverse_func fn, void *flag);
 void eeh_pe_restore_bars(struct eeh_pe *pe);
@@ -209,10 +221,12 @@ unsigned long eeh_check_failure(const volatile void __iomem *token,
                                unsigned long val);
 int eeh_dev_check_failure(struct eeh_dev *edev);
 void eeh_addr_cache_build(void);
+void eeh_add_device_early(struct device_node *);
 void eeh_add_device_tree_early(struct device_node *);
+void eeh_add_device_late(struct pci_dev *);
 void eeh_add_device_tree_late(struct pci_bus *);
 void eeh_add_sysfs_files(struct pci_bus *);
-void eeh_remove_bus_device(struct pci_dev *, int);
+void eeh_remove_device(struct pci_dev *);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
@@ -252,13 +266,17 @@ static inline unsigned long eeh_check_failure(const volatile void __iomem *token
 
 static inline void eeh_addr_cache_build(void) { }
 
+static inline void eeh_add_device_early(struct device_node *dn) { }
+
 static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
+static inline void eeh_add_device_late(struct pci_dev *dev) { }
+
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
 
 static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
 
-static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
+static inline void eeh_remove_device(struct pci_dev *dev) { }
 
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
index ba713f166fa57fb2f9b08002a8a5cf8c0162d196..10be1dd01c6b4bcd79f88725f9b5067dc8a0db8a 100644 (file)
@@ -96,10 +96,11 @@ static inline bool arch_irqs_disabled(void)
 #endif
 
 #define hard_irq_disable()     do {                    \
-       u8 _was_enabled = get_paca()->soft_enabled;     \
+       u8 _was_enabled;                                \
        __hard_irq_disable();                           \
-       get_paca()->soft_enabled = 0;                   \
-       get_paca()->irq_happened |= PACA_IRQ_HARD_DIS;  \
+       _was_enabled = local_paca->soft_enabled;        \
+       local_paca->soft_enabled = 0;                   \
+       local_paca->irq_happened |= PACA_IRQ_HARD_DIS;  \
        if (_was_enabled)                               \
                trace_hardirqs_off();                   \
 } while(0)
index c1df590ec4440a96f81b97f6048ad79a7f326179..49fa55bfbac4fba38f26368cbbdcdf1513aa590c 100644 (file)
@@ -82,10 +82,9 @@ struct exception_table_entry;
 void sort_ex_table(struct exception_table_entry *start,
                   struct exception_table_entry *finish);
 
-#ifdef CONFIG_MODVERSIONS
+#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
 #define ARCH_RELOCATES_KCRCTAB
-
-extern const unsigned long reloc_start[];
+#define reloc_start PHYSICAL_START
 #endif
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MODULE_H */
index 2c1d8cb9b26562a295ab6b6016261b0d692df30b..32d0d2018faf84afe15814f13cb7f1fe4933fa4e 100644 (file)
@@ -209,7 +209,6 @@ static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
-extern void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe);
 extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
index 5d7d9c2a547373dbb692ebded8b519df476bb2e4..a6840e4e24f7abe68d918d6dc576bcab18d0183d 100644 (file)
 #define PVR_970MP      0x0044
 #define PVR_970GX      0x0045
 #define PVR_POWER7p    0x004A
-#define PVR_POWER8     0x004B
+#define PVR_POWER8E    0x004B
+#define PVR_POWER8     0x004D
 #define PVR_BE         0x0070
 #define PVR_PA6T       0x0090
 
index 2a45d0f043852a33cc41826c7835c59471b1ed60..22973a74df7342b1146a3dd2881432c3cd8ad2b8 100644 (file)
@@ -494,9 +494,27 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_restore            = __restore_cpu_power7,
                .platform               = "power7+",
        },
-       {       /* Power8 */
+       {       /* Power8E */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x004b0000,
+               .cpu_name               = "POWER8E (raw)",
+               .cpu_features           = CPU_FTRS_POWER8,
+               .cpu_user_features      = COMMON_USER_POWER8,
+               .cpu_user_features2     = COMMON_USER2_POWER8,
+               .mmu_features           = MMU_FTRS_POWER8,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .num_pmcs               = 6,
+               .pmc_type               = PPC_PMC_IBM,
+               .oprofile_cpu_type      = "ppc64/power8",
+               .oprofile_type          = PPC_OPROFILE_INVALID,
+               .cpu_setup              = __setup_cpu_power8,
+               .cpu_restore            = __restore_cpu_power8,
+               .platform               = "power8",
+       },
+       {       /* Power8 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x004d0000,
                .cpu_name               = "POWER8 (raw)",
                .cpu_features           = CPU_FTRS_POWER8,
                .cpu_user_features      = COMMON_USER_POWER8,
index 39954fe941b87e45a95951f9c39bb2beae6724db..ea9414c8088d01289411eded7d67315c9a2e8661 100644 (file)
@@ -231,7 +231,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
 void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
 {
        size_t loglen = 0;
-       struct eeh_dev *edev;
+       struct eeh_dev *edev, *tmp;
        bool valid_cfg_log = true;
 
        /*
@@ -251,7 +251,7 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
                eeh_pe_restore_bars(pe);
 
                pci_regs_buf[0] = 0;
-               eeh_pe_for_each_dev(pe, edev) {
+               eeh_pe_for_each_dev(pe, edev, tmp) {
                        loglen += eeh_gather_pci_data(edev, pci_regs_buf + loglen,
                                                      EEH_PCI_REGS_LOG_LEN - loglen);
                }
@@ -499,8 +499,6 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon
        }
 
        eeh_dev_check_failure(edev);
-
-       pci_dev_put(eeh_dev_to_pci_dev(edev));
        return val;
 }
 
@@ -838,7 +836,7 @@ core_initcall_sync(eeh_init);
  * on the CEC architecture, type of the device, on earlier boot
  * command-line arguments & etc.
  */
-static void eeh_add_device_early(struct device_node *dn)
+void eeh_add_device_early(struct device_node *dn)
 {
        struct pci_controller *phb;
 
@@ -886,7 +884,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
  * This routine must be used to complete EEH initialization for PCI
  * devices that were added after system boot (e.g. hotplug, dlpar).
  */
-static void eeh_add_device_late(struct pci_dev *dev)
+void eeh_add_device_late(struct pci_dev *dev)
 {
        struct device_node *dn;
        struct eeh_dev *edev;
@@ -902,9 +900,23 @@ static void eeh_add_device_late(struct pci_dev *dev)
                pr_debug("EEH: Already referenced !\n");
                return;
        }
-       WARN_ON(edev->pdev);
 
-       pci_dev_get(dev);
+       /*
+        * The EEH cache might not be removed correctly because of
+        * unbalanced kref to the device during unplug time, which
+        * relies on pcibios_release_device(). So we have to remove
+        * that here explicitly.
+        */
+       if (edev->pdev) {
+               eeh_rmv_from_parent_pe(edev);
+               eeh_addr_cache_rmv_dev(edev->pdev);
+               eeh_sysfs_remove_device(edev->pdev);
+               edev->mode &= ~EEH_DEV_SYSFS;
+
+               edev->pdev = NULL;
+               dev->dev.archdata.edev = NULL;
+       }
+
        edev->pdev = dev;
        dev->dev.archdata.edev = edev;
 
@@ -967,7 +979,6 @@ EXPORT_SYMBOL_GPL(eeh_add_sysfs_files);
 /**
  * eeh_remove_device - Undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
- * @purge_pe: remove the PE or not
  *
  * This routine should be called when a device is removed from
  * a running system (e.g. by hotplug or dlpar).  It unregisters
@@ -975,7 +986,7 @@ EXPORT_SYMBOL_GPL(eeh_add_sysfs_files);
  * this device will no longer be detected after this call; thus,
  * i/o errors affecting this slot may leave this device unusable.
  */
-static void eeh_remove_device(struct pci_dev *dev, int purge_pe)
+void eeh_remove_device(struct pci_dev *dev)
 {
        struct eeh_dev *edev;
 
@@ -986,42 +997,29 @@ static void eeh_remove_device(struct pci_dev *dev, int purge_pe)
        /* Unregister the device with the EEH/PCI address search system */
        pr_debug("EEH: Removing device %s\n", pci_name(dev));
 
-       if (!edev || !edev->pdev) {
+       if (!edev || !edev->pdev || !edev->pe) {
                pr_debug("EEH: Not referenced !\n");
                return;
        }
+
+       /*
+        * During the hotplug for EEH error recovery, we need the EEH
+        * device attached to the parent PE in order for BAR restore
+        * a bit later. So we keep it for BAR restore and remove it
+        * from the parent PE during the BAR resotre.
+        */
        edev->pdev = NULL;
        dev->dev.archdata.edev = NULL;
-       pci_dev_put(dev);
+       if (!(edev->pe->state & EEH_PE_KEEP))
+               eeh_rmv_from_parent_pe(edev);
+       else
+               edev->mode |= EEH_DEV_DISCONNECTED;
 
-       eeh_rmv_from_parent_pe(edev, purge_pe);
        eeh_addr_cache_rmv_dev(dev);
        eeh_sysfs_remove_device(dev);
+       edev->mode &= ~EEH_DEV_SYSFS;
 }
 
-/**
- * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
- * @dev: PCI device
- * @purge_pe: remove the corresponding PE or not
- *
- * This routine must be called when a device is removed from the
- * running system through hotplug or dlpar. The corresponding
- * PCI address cache will be removed.
- */
-void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe)
-{
-       struct pci_bus *bus = dev->subordinate;
-       struct pci_dev *child, *tmp;
-
-       eeh_remove_device(dev, purge_pe);
-
-       if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-               list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
-                        eeh_remove_bus_device(child, purge_pe);
-       }
-}
-EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
-
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
        if (0 == eeh_subsystem_enabled) {
index f9ac1232a746c595d696ef7b66469a093070c877..e8c9fd546a5c477b4c7755527ffb19dd64c04eca 100644 (file)
@@ -68,16 +68,12 @@ static inline struct eeh_dev *__eeh_addr_cache_get_device(unsigned long addr)
                struct pci_io_addr_range *piar;
                piar = rb_entry(n, struct pci_io_addr_range, rb_node);
 
-               if (addr < piar->addr_lo) {
+               if (addr < piar->addr_lo)
                        n = n->rb_left;
-               } else {
-                       if (addr > piar->addr_hi) {
-                               n = n->rb_right;
-                       } else {
-                               pci_dev_get(piar->pcidev);
-                               return piar->edev;
-                       }
-               }
+               else if (addr > piar->addr_hi)
+                       n = n->rb_right;
+               else
+                       return piar->edev;
        }
 
        return NULL;
@@ -156,7 +152,6 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
        if (!piar)
                return NULL;
 
-       pci_dev_get(dev);
        piar->addr_lo = alo;
        piar->addr_hi = ahi;
        piar->edev = pci_dev_to_eeh_dev(dev);
@@ -250,7 +245,6 @@ restart:
 
                if (piar->pcidev == dev) {
                        rb_erase(n, &pci_io_addr_cache_root.rb_root);
-                       pci_dev_put(piar->pcidev);
                        kfree(piar);
                        goto restart;
                }
@@ -302,12 +296,10 @@ void eeh_addr_cache_build(void)
                if (!edev)
                        continue;
 
-               pci_dev_get(dev);  /* matching put is in eeh_remove_device() */
                dev->dev.archdata.edev = edev;
                edev->pdev = dev;
 
                eeh_addr_cache_insert_dev(dev);
-
                eeh_sysfs_add_device(dev);
        }
 
index 2b1ce17cae504d95a5be5e04e16828a5e3f7516e..36bed5a12750b639e2c305153585869be536ddef 100644 (file)
@@ -143,10 +143,14 @@ static void eeh_disable_irq(struct pci_dev *dev)
 static void eeh_enable_irq(struct pci_dev *dev)
 {
        struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
+       struct irq_desc *desc;
 
        if ((edev->mode) & EEH_DEV_IRQ_DISABLED) {
                edev->mode &= ~EEH_DEV_IRQ_DISABLED;
-               enable_irq(dev->irq);
+
+               desc = irq_to_desc(dev->irq);
+               if (desc && desc->depth > 0)
+                       enable_irq(dev->irq);
        }
 }
 
@@ -338,6 +342,54 @@ static void *eeh_report_failure(void *data, void *userdata)
        return NULL;
 }
 
+static void *eeh_rmv_device(void *data, void *userdata)
+{
+       struct pci_driver *driver;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+       int *removed = (int *)userdata;
+
+       /*
+        * Actually, we should remove the PCI bridges as well.
+        * However, that's lots of complexity to do that,
+        * particularly some of devices under the bridge might
+        * support EEH. So we just care about PCI devices for
+        * simplicity here.
+        */
+       if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+               return NULL;
+       driver = eeh_pcid_get(dev);
+       if (driver && driver->err_handler)
+               return NULL;
+
+       /* Remove it from PCI subsystem */
+       pr_debug("EEH: Removing %s without EEH sensitive driver\n",
+                pci_name(dev));
+       edev->bus = dev->bus;
+       edev->mode |= EEH_DEV_DISCONNECTED;
+       (*removed)++;
+
+       pci_stop_and_remove_bus_device(dev);
+
+       return NULL;
+}
+
+static void *eeh_pe_detach_dev(void *data, void *userdata)
+{
+       struct eeh_pe *pe = (struct eeh_pe *)data;
+       struct eeh_dev *edev, *tmp;
+
+       eeh_pe_for_each_dev(pe, edev, tmp) {
+               if (!(edev->mode & EEH_DEV_DISCONNECTED))
+                       continue;
+
+               edev->mode &= ~(EEH_DEV_DISCONNECTED | EEH_DEV_IRQ_DISABLED);
+               eeh_rmv_from_parent_pe(edev);
+       }
+
+       return NULL;
+}
+
 /**
  * eeh_reset_device - Perform actual reset of a pci slot
  * @pe: EEH PE
@@ -349,8 +401,9 @@ static void *eeh_report_failure(void *data, void *userdata)
  */
 static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 {
+       struct pci_bus *frozen_bus = eeh_pe_bus_get(pe);
        struct timeval tstamp;
-       int cnt, rc;
+       int cnt, rc, removed = 0;
 
        /* pcibios will clear the counter; save the value */
        cnt = pe->freeze_count;
@@ -362,8 +415,11 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
         * devices are expected to be attached soon when calling
         * into pcibios_add_pci_devices().
         */
+       eeh_pe_state_mark(pe, EEH_PE_KEEP);
        if (bus)
-               __pcibios_remove_pci_devices(bus, 0);
+               pcibios_remove_pci_devices(bus);
+       else if (frozen_bus)
+               eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed);
 
        /* Reset the pci controller. (Asserts RST#; resets config space).
         * Reconfigure bridges and devices. Don't try to bring the system
@@ -384,9 +440,24 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
         * potentially weird things happen.
         */
        if (bus) {
+               pr_info("EEH: Sleep 5s ahead of complete hotplug\n");
                ssleep(5);
+
+               /*
+                * The EEH device is still connected with its parent
+                * PE. We should disconnect it so the binding can be
+                * rebuilt when adding PCI devices.
+                */
+               eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
                pcibios_add_pci_devices(bus);
+       } else if (frozen_bus && removed) {
+               pr_info("EEH: Sleep 5s ahead of partial hotplug\n");
+               ssleep(5);
+
+               eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
+               pcibios_add_pci_devices(frozen_bus);
        }
+       eeh_pe_state_clear(pe, EEH_PE_KEEP);
 
        pe->tstamp = tstamp;
        pe->freeze_count = cnt;
index 016588a6f5ede19c9c45b0ab6a3bd44cfce962ae..f9450537e335a350354dec35ff5fdf15876ef0a6 100644 (file)
@@ -149,8 +149,8 @@ static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe,
  * callback returns something other than NULL, or no more PEs
  * to be traversed.
  */
-static void *eeh_pe_traverse(struct eeh_pe *root,
-                       eeh_traverse_func fn, void *flag)
+void *eeh_pe_traverse(struct eeh_pe *root,
+                     eeh_traverse_func fn, void *flag)
 {
        struct eeh_pe *pe;
        void *ret;
@@ -176,7 +176,7 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
                eeh_traverse_func fn, void *flag)
 {
        struct eeh_pe *pe;
-       struct eeh_dev *edev;
+       struct eeh_dev *edev, *tmp;
        void *ret;
 
        if (!root) {
@@ -186,7 +186,7 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
 
        /* Traverse root PE */
        for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
-               eeh_pe_for_each_dev(pe, edev) {
+               eeh_pe_for_each_dev(pe, edev, tmp) {
                        ret = fn(edev, flag);
                        if (ret)
                                return ret;
@@ -333,7 +333,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
                while (parent) {
                        if (!(parent->type & EEH_PE_INVALID))
                                break;
-                       parent->type &= ~EEH_PE_INVALID;
+                       parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP);
                        parent = parent->parent;
                }
                pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
@@ -397,21 +397,20 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 /**
  * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE
  * @edev: EEH device
- * @purge_pe: remove PE or not
  *
  * The PE hierarchy tree might be changed when doing PCI hotplug.
  * Also, the PCI devices or buses could be removed from the system
  * during EEH recovery. So we have to call the function remove the
  * corresponding PE accordingly if necessary.
  */
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
 {
        struct eeh_pe *pe, *parent, *child;
        int cnt;
 
        if (!edev->pe) {
-               pr_warning("%s: No PE found for EEH device %s\n",
-                       __func__, edev->dn->full_name);
+               pr_debug("%s: No PE found for EEH device %s\n",
+                        __func__, edev->dn->full_name);
                return -EEXIST;
        }
 
@@ -431,7 +430,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
                if (pe->type & EEH_PE_PHB)
                        break;
 
-               if (purge_pe) {
+               if (!(pe->state & EEH_PE_KEEP)) {
                        if (list_empty(&pe->edevs) &&
                            list_empty(&pe->child_list)) {
                                list_del(&pe->child);
@@ -502,7 +501,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
 {
        struct eeh_pe *pe = (struct eeh_pe *)data;
        int state = *((int *)flag);
-       struct eeh_dev *tmp;
+       struct eeh_dev *edev, *tmp;
        struct pci_dev *pdev;
 
        /*
@@ -512,8 +511,8 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
         * the PCI device driver.
         */
        pe->state |= state;
-       eeh_pe_for_each_dev(pe, tmp) {
-               pdev = eeh_dev_to_pci_dev(tmp);
+       eeh_pe_for_each_dev(pe, edev, tmp) {
+               pdev = eeh_dev_to_pci_dev(edev);
                if (pdev)
                        pdev->error_state = pci_channel_io_frozen;
        }
@@ -579,7 +578,7 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state)
  * blocked on normal path during the stage. So we need utilize
  * eeh operations, which is always permitted.
  */
-static void eeh_bridge_check_link(struct pci_dev *pdev,
+static void eeh_bridge_check_link(struct eeh_dev *edev,
                                  struct device_node *dn)
 {
        int cap;
@@ -590,16 +589,17 @@ static void eeh_bridge_check_link(struct pci_dev *pdev,
         * We only check root port and downstream ports of
         * PCIe switches
         */
-       if (!pci_is_pcie(pdev) ||
-           (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
-            pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM))
+       if (!(edev->mode & (EEH_DEV_ROOT_PORT | EEH_DEV_DS_PORT)))
                return;
 
-       pr_debug("%s: Check PCIe link for %s ...\n",
-                __func__, pci_name(pdev));
+       pr_debug("%s: Check PCIe link for %04x:%02x:%02x.%01x ...\n",
+                __func__, edev->phb->global_number,
+                edev->config_addr >> 8,
+                PCI_SLOT(edev->config_addr & 0xFF),
+                PCI_FUNC(edev->config_addr & 0xFF));
 
        /* Check slot status */
-       cap = pdev->pcie_cap;
+       cap = edev->pcie_cap;
        eeh_ops->read_config(dn, cap + PCI_EXP_SLTSTA, 2, &val);
        if (!(val & PCI_EXP_SLTSTA_PDS)) {
                pr_debug("  No card in the slot (0x%04x) !\n", val);
@@ -653,8 +653,7 @@ static void eeh_bridge_check_link(struct pci_dev *pdev,
 #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
 #define SAVED_BYTE(OFF)        (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
 
-static void eeh_restore_bridge_bars(struct pci_dev *pdev,
-                                   struct eeh_dev *edev,
+static void eeh_restore_bridge_bars(struct eeh_dev *edev,
                                    struct device_node *dn)
 {
        int i;
@@ -680,7 +679,7 @@ static void eeh_restore_bridge_bars(struct pci_dev *pdev,
        eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]);
 
        /* Check the PCIe link is ready */
-       eeh_bridge_check_link(pdev, dn);
+       eeh_bridge_check_link(edev, dn);
 }
 
 static void eeh_restore_device_bars(struct eeh_dev *edev,
@@ -729,19 +728,12 @@ static void eeh_restore_device_bars(struct eeh_dev *edev,
  */
 static void *eeh_restore_one_device_bars(void *data, void *flag)
 {
-       struct pci_dev *pdev = NULL;
        struct eeh_dev *edev = (struct eeh_dev *)data;
        struct device_node *dn = eeh_dev_to_of_node(edev);
 
-       /* Trace the PCI bridge */
-       if (eeh_probe_mode_dev()) {
-               pdev = eeh_dev_to_pci_dev(edev);
-               if (pdev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
-                        pdev = NULL;
-        }
-
-       if (pdev)
-               eeh_restore_bridge_bars(pdev, edev, dn);
+       /* Do special restore for bridges */
+       if (edev->mode & EEH_DEV_BRIDGE)
+               eeh_restore_bridge_bars(edev, dn);
        else
                eeh_restore_device_bars(edev, dn);
 
index e7ae3484918c29639ff1a1baa597579a973fe6cd..5d753d4f2c75938e5fdd2c75b821ff98877cd2c9 100644 (file)
@@ -56,19 +56,40 @@ EEH_SHOW_ATTR(eeh_pe_config_addr,  pe_config_addr,  "0x%x");
 
 void eeh_sysfs_add_device(struct pci_dev *pdev)
 {
+       struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
        int rc=0;
 
+       if (edev && (edev->mode & EEH_DEV_SYSFS))
+               return;
+
        rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
        rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
        rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
 
        if (rc)
                printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
+       else if (edev)
+               edev->mode |= EEH_DEV_SYSFS;
 }
 
 void eeh_sysfs_remove_device(struct pci_dev *pdev)
 {
+       struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
+
+       /*
+        * The parent directory might have been removed. We needn't
+        * continue for that case.
+        */
+       if (!pdev->dev.kobj.sd) {
+               if (edev)
+                       edev->mode &= ~EEH_DEV_SYSFS;
+               return;
+       }
+
        device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
        device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
        device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
+
+       if (edev)
+               edev->mode &= ~EEH_DEV_SYSFS;
 }
index f46914a0f33ea6fd3cacbdddb76288722dfb42cb..7d22a675fe1a3338d5f1a9d64eb44ce70d8f8f7b 100644 (file)
@@ -1462,6 +1462,8 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
        /* Allocate bus and devices resources */
        pcibios_allocate_bus_resources(bus);
        pcibios_claim_one_bus(bus);
+       if (!pci_has_flag(PCI_PROBE_ONLY))
+               pci_assign_unassigned_bus_resources(bus);
 
        /* Fixup EEH */
        eeh_add_device_tree_late(bus);
index 3f608800c06b59082116c3bcd642d26146b357c2..c1e17ae68a08047a0a60154aed49684d8b4aad2f 100644 (file)
 #include <asm/eeh.h>
 
 /**
- * __pcibios_remove_pci_devices - remove all devices under this bus
+ * pcibios_release_device - release PCI device
+ * @dev: PCI device
+ *
+ * The function is called before releasing the indicated PCI device.
+ */
+void pcibios_release_device(struct pci_dev *dev)
+{
+       eeh_remove_device(dev);
+}
+
+/**
+ * pcibios_remove_pci_devices - remove all devices under this bus
  * @bus: the indicated PCI bus
- * @purge_pe: destroy the PE on removal of PCI devices
  *
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
- * By default, the corresponding PE will be destroied during the
- * normal PCI hotplug path. For PCI hotplug during EEH recovery,
- * the corresponding PE won't be destroied and deallocated.
  */
-void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe)
+void pcibios_remove_pci_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev, *tmp;
        struct pci_bus *child_bus;
 
        /* First go down child busses */
        list_for_each_entry(child_bus, &bus->children, node)
-               __pcibios_remove_pci_devices(child_bus, purge_pe);
+               pcibios_remove_pci_devices(child_bus);
 
        pr_debug("PCI: Removing devices on bus %04x:%02x\n",
                 pci_domain_nr(bus),  bus->number);
        list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
-               pr_debug("     * Removing %s...\n", pci_name(dev));
-               eeh_remove_bus_device(dev, purge_pe);
+               pr_debug("   Removing %s...\n", pci_name(dev));
                pci_stop_and_remove_bus_device(dev);
        }
 }
 
-/**
- * pcibios_remove_pci_devices - remove all devices under this bus
- * @bus: the indicated PCI bus
- *
- * Remove all of the PCI devices under this bus both from the
- * linux pci device tree, and from the powerpc EEH address cache.
- */
-void pcibios_remove_pci_devices(struct pci_bus *bus)
-{
-       __pcibios_remove_pci_devices(bus, 1);
-}
 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
 /**
@@ -76,7 +71,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
  */
 void pcibios_add_pci_devices(struct pci_bus * bus)
 {
-       int slotno, num, mode, pass, max;
+       int slotno, mode, pass, max;
        struct pci_dev *dev;
        struct device_node *dn = pci_bus_to_OF_node(bus);
 
@@ -90,11 +85,15 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
                /* use ofdt-based probe */
                of_rescan_bus(dn, bus);
        } else if (mode == PCI_PROBE_NORMAL) {
-               /* use legacy probe */
+               /*
+                * Use legacy probe. In the partial hotplug case, we
+                * probably have grandchildren devices unplugged. So
+                * we don't check the return value from pci_scan_slot() in
+                * order for fully rescan all the way down to pick them up.
+                * They can have been removed during partial hotplug.
+                */
                slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
-               num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
-               if (!num)
-                       return;
+               pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
                pcibios_setup_bus_devices(bus);
                max = bus->busn_res.start;
                for (pass = 0; pass < 2; pass++) {
index 6b0ba5854d9960aff03bbd01b810543c9e369588..15d9105323bf5048009428c4bfc83d06edffb38f 100644 (file)
@@ -230,11 +230,14 @@ void of_scan_pci_bridge(struct pci_dev *dev)
                return;
        }
 
-       bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
+       bus = pci_find_bus(pci_domain_nr(dev->bus), busrange[0]);
        if (!bus) {
-               printk(KERN_ERR "Failed to create pci bus for %s\n",
-                      node->full_name);
-               return;
+               bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
+               if (!bus) {
+                       printk(KERN_ERR "Failed to create pci bus for %s\n",
+                              node->full_name);
+                       return;
+               }
        }
 
        bus->primary = dev->bus->number;
@@ -292,6 +295,38 @@ void of_scan_pci_bridge(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(of_scan_pci_bridge);
 
+static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus,
+                           struct device_node *dn)
+{
+       struct pci_dev *dev = NULL;
+       const u32 *reg;
+       int reglen, devfn;
+
+       pr_debug("  * %s\n", dn->full_name);
+       if (!of_device_is_available(dn))
+               return NULL;
+
+       reg = of_get_property(dn, "reg", &reglen);
+       if (reg == NULL || reglen < 20)
+               return NULL;
+       devfn = (reg[0] >> 8) & 0xff;
+
+       /* Check if the PCI device is already there */
+       dev = pci_get_slot(bus, devfn);
+       if (dev) {
+               pci_dev_put(dev);
+               return dev;
+       }
+
+       /* create a new pci_dev for this device */
+       dev = of_create_pci_dev(dn, bus, devfn);
+       if (!dev)
+               return NULL;
+
+       pr_debug("  dev header type: %x\n", dev->hdr_type);
+       return dev;
+}
+
 /**
  * __of_scan_bus - given a PCI bus node, setup bus and scan for child devices
  * @node: device tree node for the PCI bus
@@ -302,8 +337,6 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus,
                          int rescan_existing)
 {
        struct device_node *child;
-       const u32 *reg;
-       int reglen, devfn;
        struct pci_dev *dev;
 
        pr_debug("of_scan_bus(%s) bus no %d...\n",
@@ -311,16 +344,7 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus,
 
        /* Scan direct children */
        for_each_child_of_node(node, child) {
-               pr_debug("  * %s\n", child->full_name);
-               if (!of_device_is_available(child))
-                       continue;
-               reg = of_get_property(child, "reg", &reglen);
-               if (reg == NULL || reglen < 20)
-                       continue;
-               devfn = (reg[0] >> 8) & 0xff;
-
-               /* create a new pci_dev for this device */
-               dev = of_create_pci_dev(child, bus, devfn);
+               dev = of_scan_pci_dev(bus, child);
                if (!dev)
                        continue;
                pr_debug("    dev header type: %x\n", dev->hdr_type);
index 5eccda9fd33f5396b5a5c231db1c8051bcacf747..607902424e7377046943a14f7a8aeb56471327e4 100644 (file)
@@ -644,7 +644,8 @@ unsigned char ibm_architecture_vec[] = {
        W(0xfffe0000), W(0x003a0000),   /* POWER5/POWER5+ */
        W(0xffff0000), W(0x003e0000),   /* POWER6 */
        W(0xffff0000), W(0x003f0000),   /* POWER7 */
-       W(0xffff0000), W(0x004b0000),   /* POWER8 */
+       W(0xffff0000), W(0x004b0000),   /* POWER8E */
+       W(0xffff0000), W(0x004d0000),   /* POWER8 */
        W(0xffffffff), W(0x0f000004),   /* all 2.07-compliant */
        W(0xffffffff), W(0x0f000003),   /* all 2.06-compliant */
        W(0xffffffff), W(0x0f000002),   /* all 2.05-compliant */
@@ -706,7 +707,7 @@ unsigned char ibm_architecture_vec[] = {
         * must match by the macro below. Update the definition if
         * the structure layout changes.
         */
-#define IBM_ARCH_VEC_NRCORES_OFFSET    117
+#define IBM_ARCH_VEC_NRCORES_OFFSET    125
        W(NR_CPUS),                     /* number of cores supported */
        0,
        0,
index 654e479802f2098afb74c0fea0bb0b68e25707f5..f096e72262f41d121398f8fa27d5286bd8641bf4 100644 (file)
@@ -38,9 +38,6 @@ jiffies = jiffies_64 + 4;
 #endif
 SECTIONS
 {
-       . = 0;
-       reloc_start = .;
-
        . = KERNELBASE;
 
 /*
index 3f0c30ae4791db7597c3fac74740e09e0fb3b7c1..c33d939120c970f3f800b42b5dfa3739e28ac16f 100644 (file)
@@ -43,6 +43,7 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
 {
        unsigned long va;
        unsigned int penc;
+       unsigned long sllp;
 
        /*
         * We need 14 to 65 bits of va for a tlibe of 4K page
@@ -64,7 +65,9 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
                /* clear out bits after (52) [0....52.....63] */
                va &= ~((1ul << (64 - 52)) - 1);
                va |= ssize << 8;
-               va |= mmu_psize_defs[apsize].sllp << 6;
+               sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) |
+                       ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4);
+               va |= sllp << 5;
                asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
                             : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
                             : "memory");
@@ -98,6 +101,7 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
 {
        unsigned long va;
        unsigned int penc;
+       unsigned long sllp;
 
        /* VPN_SHIFT can be atmost 12 */
        va = vpn << VPN_SHIFT;
@@ -113,7 +117,9 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
                /* clear out bits after(52) [0....52.....63] */
                va &= ~((1ul << (64 - 52)) - 1);
                va |= ssize << 8;
-               va |= mmu_psize_defs[apsize].sllp << 6;
+               sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) |
+                       ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4);
+               va |= sllp << 5;
                asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
                             : : "r"(va) : "memory");
                break;
@@ -554,6 +560,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
                        seg_off |= vpi << shift;
                }
                *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+               break;
        case MMU_SEGSIZE_1T:
                /* We only have 40 - 23 bits of seg_off in avpn */
                seg_off = (avpn & 0x1ffff) << 23;
@@ -563,6 +570,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
                        seg_off |= vpi << shift;
                }
                *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+               break;
        default:
                *vpn = size = 0;
        }
index a3985aee77fec1ecd2fe9756257e3a46b9643b94..24a45f91c65f69480119055e6d8820f52f07582b 100644 (file)
@@ -1252,8 +1252,11 @@ nocheck:
 
        ret = 0;
  out:
-       if (has_branch_stack(event))
+       if (has_branch_stack(event)) {
                power_pmu_bhrb_enable(event);
+               cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
+                                       event->attr.branch_sample_type);
+       }
 
        perf_pmu_enable(event->pmu);
        local_irq_restore(flags);
index 96a64d6a8bdf3dfbba1c5a57f16bcb38d3c8a7ce..7466374d2787cca701ecef97da54b723dee09026 100644 (file)
@@ -561,18 +561,13 @@ static int power8_generic_events[] = {
 static u64 power8_bhrb_filter_map(u64 branch_sample_type)
 {
        u64 pmu_bhrb_filter = 0;
-       u64 br_privilege = branch_sample_type & ONLY_PLM;
 
-       /* BHRB and regular PMU events share the same prvillege state
+       /* BHRB and regular PMU events share the same privilege state
         * filter configuration. BHRB is always recorded along with a
-        * regular PMU event. So privilege state filter criteria for BHRB
-        * and the companion PMU events has to be the same. As a default
-        * "perf record" tool sets all privillege bits ON when no filter
-        * criteria is provided in the command line. So as along as all
-        * privillege bits are ON or they are OFF, we are good to go.
+        * regular PMU event. As the privilege state filter is handled
+        * in the basic PMC configuration of the accompanying regular
+        * PMU event, we ignore any separate BHRB specific request.
         */
-       if ((br_privilege != 7) && (br_privilege != 0))
-               return -1;
 
        /* No branch filter requested */
        if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
@@ -621,10 +616,19 @@ static struct power_pmu power8_pmu = {
 
 static int __init init_power8_pmu(void)
 {
+       int rc;
+
        if (!cur_cpu_spec->oprofile_cpu_type ||
            strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8"))
                return -ENODEV;
 
-       return register_power_pmu(&power8_pmu);
+       rc = register_power_pmu(&power8_pmu);
+       if (rc)
+               return rc;
+
+       /* Tell userspace that EBB is supported */
+       cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
+
+       return 0;
 }
 early_initcall(init_power8_pmu);
index 969cce73055af337f3b15c9c12df27dc3aebb4ed..79663d26e6eaa1de8749c6994316737f991106ab 100644 (file)
@@ -114,7 +114,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
         * the root bridge. So it's not reasonable to continue
         * the probing.
         */
-       if (!dn || !edev)
+       if (!dn || !edev || edev->pe)
                return 0;
 
        /* Skip for PCI-ISA bridge */
@@ -122,8 +122,19 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
                return 0;
 
        /* Initialize eeh device */
-       edev->class_code        = dev->class;
-       edev->mode              = 0;
+       edev->class_code = dev->class;
+       edev->mode      &= 0xFFFFFF00;
+       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+               edev->mode |= EEH_DEV_BRIDGE;
+       if (pci_is_pcie(dev)) {
+               edev->pcie_cap = pci_pcie_cap(dev);
+
+               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+                       edev->mode |= EEH_DEV_ROOT_PORT;
+               else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM)
+                       edev->mode |= EEH_DEV_DS_PORT;
+       }
+
        edev->config_addr       = ((dev->bus->number << 8) | dev->devfn);
        edev->pe_config_addr    = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff);
 
index 49b57b9f835d787977817db8f093d40c354ac7d5..d8140b125e62508720388d683a5028199d62ff28 100644 (file)
@@ -1266,7 +1266,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np,
                opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
 }
 
-void pnv_pci_init_ioda2_phb(struct device_node *np)
+void __init pnv_pci_init_ioda2_phb(struct device_node *np)
 {
        pnv_pci_init_ioda_phb(np, 0, PNV_PHB_IODA2);
 }
index 1bd3399146ed6f945f24308ea95883bffdce8d28..62b4f8025de005ad77bdbfcd42024d25614eb79c 100644 (file)
@@ -19,7 +19,6 @@ config PPC_PSERIES
        select ZLIB_DEFLATE
        select PPC_DOORBELL
        select HAVE_CONTEXT_TRACKING
-       select HOTPLUG if SMP
        select HOTPLUG_CPU if SMP
        default y
 
index b456b157d33d107842a42d3b0c3d0da36e9ea121..7fbc25b1813fe59ea80eceba65cb2a76027c0eec 100644 (file)
@@ -133,6 +133,48 @@ static int pseries_eeh_init(void)
        return 0;
 }
 
+static int pseries_eeh_cap_start(struct device_node *dn)
+{
+       struct pci_dn *pdn = PCI_DN(dn);
+       u32 status;
+
+       if (!pdn)
+               return 0;
+
+       rtas_read_config(pdn, PCI_STATUS, 2, &status);
+       if (!(status & PCI_STATUS_CAP_LIST))
+               return 0;
+
+       return PCI_CAPABILITY_LIST;
+}
+
+
+static int pseries_eeh_find_cap(struct device_node *dn, int cap)
+{
+       struct pci_dn *pdn = PCI_DN(dn);
+       int pos = pseries_eeh_cap_start(dn);
+       int cnt = 48;   /* Maximal number of capabilities */
+       u32 id;
+
+       if (!pos)
+               return 0;
+
+        while (cnt--) {
+               rtas_read_config(pdn, pos, 1, &pos);
+               if (pos < 0x40)
+                       break;
+               pos &= ~3;
+               rtas_read_config(pdn, pos + PCI_CAP_LIST_ID, 1, &id);
+               if (id == 0xff)
+                       break;
+               if (id == cap)
+                       return pos;
+               pos += PCI_CAP_LIST_NEXT;
+       }
+
+       return 0;
+}
+
 /**
  * pseries_eeh_of_probe - EEH probe on the given device
  * @dn: OF node
@@ -146,14 +188,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
 {
        struct eeh_dev *edev;
        struct eeh_pe pe;
+       struct pci_dn *pdn = PCI_DN(dn);
        const u32 *class_code, *vendor_id, *device_id;
        const u32 *regs;
+       u32 pcie_flags;
        int enable = 0;
        int ret;
 
        /* Retrieve OF node and eeh device */
        edev = of_node_to_eeh_dev(dn);
-       if (!of_device_is_available(dn))
+       if (edev->pe || !of_device_is_available(dn))
                return NULL;
 
        /* Retrieve class/vendor/device IDs */
@@ -167,9 +211,26 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
        if (dn->type && !strcmp(dn->type, "isa"))
                return NULL;
 
-       /* Update class code and mode of eeh device */
+       /*
+        * Update class code and mode of eeh device. We need
+        * correctly reflects that current device is root port
+        * or PCIe switch downstream port.
+        */
        edev->class_code = *class_code;
-       edev->mode = 0;
+       edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP);
+       edev->mode &= 0xFFFFFF00;
+       if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               edev->mode |= EEH_DEV_BRIDGE;
+               if (edev->pcie_cap) {
+                       rtas_read_config(pdn, edev->pcie_cap + PCI_EXP_FLAGS,
+                                        2, &pcie_flags);
+                       pcie_flags = (pcie_flags & PCI_EXP_FLAGS_TYPE) >> 4;
+                       if (pcie_flags == PCI_EXP_TYPE_ROOT_PORT)
+                               edev->mode |= EEH_DEV_ROOT_PORT;
+                       else if (pcie_flags == PCI_EXP_TYPE_DOWNSTREAM)
+                               edev->mode |= EEH_DEV_DS_PORT;
+               }
+       }
 
        /* Retrieve the device address */
        regs = of_get_property(dn, "reg", NULL);
index 02d6e21619bb6c677771c0dc6ecaabb5e1d417d5..8bad880bd177a2efaf9887b0509593401112aee4 100644 (file)
@@ -146,7 +146,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        flags = 0;
 
        /* Make pHyp happy */
-       if ((rflags & _PAGE_NO_CACHE) & !(rflags & _PAGE_WRITETHRU))
+       if ((rflags & _PAGE_NO_CACHE) && !(rflags & _PAGE_WRITETHRU))
                hpte_r &= ~_PAGE_COHERENT;
        if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N))
                flags |= H_COALESCE_CAND;
index 7b3cbde8c78378e25fb0d82ca60b58e20ffe51f5..721c0586b284d42aec0dfe69bdc178e191bcf222 100644 (file)
@@ -287,6 +287,9 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
        unsigned long *savep;
        struct rtas_error_log *h, *errhdr = NULL;
 
+       /* Mask top two bits */
+       regs->gpr[3] &= ~(0x3UL << 62);
+
        if (!VALID_FWNMI_BUFFER(regs->gpr[3])) {
                printk(KERN_ERR "FWNMI: corrupt r3 0x%016lx\n", regs->gpr[3]);
                return NULL;
index 7d6ba9db1be99696784aeba62343eeebff9c32dd..6c63c358a7e689070881361b003f102c154e9c96 100644 (file)
@@ -27,7 +27,6 @@ obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
 obj-$(CONFIG_CRYPTO_CRC32_PCLMUL) += crc32-pclmul.o
 obj-$(CONFIG_CRYPTO_SHA256_SSSE3) += sha256-ssse3.o
 obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o
-obj-$(CONFIG_CRYPTO_CRCT10DIF_PCLMUL) += crct10dif-pclmul.o
 
 # These modules require assembler to support AVX.
 ifeq ($(avx_supported),yes)
@@ -82,4 +81,3 @@ crc32c-intel-$(CONFIG_64BIT) += crc32c-pcl-intel-asm_64.o
 crc32-pclmul-y := crc32-pclmul_asm.o crc32-pclmul_glue.o
 sha256-ssse3-y := sha256-ssse3-asm.o sha256-avx-asm.o sha256-avx2-asm.o sha256_ssse3_glue.o
 sha512-ssse3-y := sha512-ssse3-asm.o sha512-avx-asm.o sha512-avx2-asm.o sha512_ssse3_glue.o
-crct10dif-pclmul-y := crct10dif-pcl-asm_64.o crct10dif-pclmul_glue.o
diff --git a/arch/x86/crypto/crct10dif-pcl-asm_64.S b/arch/x86/crypto/crct10dif-pcl-asm_64.S
deleted file mode 100644 (file)
index 35e9756..0000000
+++ /dev/null
@@ -1,643 +0,0 @@
-########################################################################
-# Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions
-#
-# Copyright (c) 2013, Intel Corporation
-#
-# Authors:
-#     Erdinc Ozturk <erdinc.ozturk@intel.com>
-#     Vinodh Gopal <vinodh.gopal@intel.com>
-#     James Guilford <james.guilford@intel.com>
-#     Tim Chen <tim.c.chen@linux.intel.com>
-#
-# This software is available to you under a choice of one of two
-# licenses.  You may choose to be licensed under the terms of the GNU
-# General Public License (GPL) Version 2, available from the file
-# COPYING in the main directory of this source tree, or the
-# OpenIB.org BSD license below:
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the
-#   distribution.
-#
-# * Neither the name of the Intel Corporation nor the names of its
-#   contributors may be used to endorse or promote products derived from
-#   this software without specific prior written permission.
-#
-#
-# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-########################################################################
-#       Function API:
-#       UINT16 crc_t10dif_pcl(
-#               UINT16 init_crc, //initial CRC value, 16 bits
-#               const unsigned char *buf, //buffer pointer to calculate CRC on
-#               UINT64 len //buffer length in bytes (64-bit data)
-#       );
-#
-#       Reference paper titled "Fast CRC Computation for Generic
-#      Polynomials Using PCLMULQDQ Instruction"
-#       URL: http://www.intel.com/content/dam/www/public/us/en/documents
-#  /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
-#
-#
-
-#include <linux/linkage.h>
-
-.text
-
-#define        arg1 %rdi
-#define        arg2 %rsi
-#define        arg3 %rdx
-
-#define        arg1_low32 %edi
-
-ENTRY(crc_t10dif_pcl)
-.align 16
-
-       # adjust the 16-bit initial_crc value, scale it to 32 bits
-       shl     $16, arg1_low32
-
-       # Allocate Stack Space
-       mov     %rsp, %rcx
-       sub     $16*2, %rsp
-       # align stack to 16 byte boundary
-       and     $~(0x10 - 1), %rsp
-
-       # check if smaller than 256
-       cmp     $256, arg3
-
-       # for sizes less than 128, we can't fold 64B at a time...
-       jl      _less_than_128
-
-
-       # load the initial crc value
-       movd    arg1_low32, %xmm10      # initial crc
-
-       # crc value does not need to be byte-reflected, but it needs
-       # to be moved to the high part of the register.
-       # because data will be byte-reflected and will align with
-       # initial crc at correct place.
-       pslldq  $12, %xmm10
-
-       movdqa  SHUF_MASK(%rip), %xmm11
-       # receive the initial 64B data, xor the initial crc value
-       movdqu  16*0(arg2), %xmm0
-       movdqu  16*1(arg2), %xmm1
-       movdqu  16*2(arg2), %xmm2
-       movdqu  16*3(arg2), %xmm3
-       movdqu  16*4(arg2), %xmm4
-       movdqu  16*5(arg2), %xmm5
-       movdqu  16*6(arg2), %xmm6
-       movdqu  16*7(arg2), %xmm7
-
-       pshufb  %xmm11, %xmm0
-       # XOR the initial_crc value
-       pxor    %xmm10, %xmm0
-       pshufb  %xmm11, %xmm1
-       pshufb  %xmm11, %xmm2
-       pshufb  %xmm11, %xmm3
-       pshufb  %xmm11, %xmm4
-       pshufb  %xmm11, %xmm5
-       pshufb  %xmm11, %xmm6
-       pshufb  %xmm11, %xmm7
-
-       movdqa  rk3(%rip), %xmm10       #xmm10 has rk3 and rk4
-                                       #imm value of pclmulqdq instruction
-                                       #will determine which constant to use
-
-       #################################################################
-       # we subtract 256 instead of 128 to save one instruction from the loop
-       sub     $256, arg3
-
-       # at this section of the code, there is 64*x+y (0<=y<64) bytes of
-       # buffer. The _fold_64_B_loop will fold 64B at a time
-       # until we have 64+y Bytes of buffer
-
-
-       # fold 64B at a time. This section of the code folds 4 xmm
-       # registers in parallel
-_fold_64_B_loop:
-
-       # update the buffer pointer
-       add     $128, arg2              #    buf += 64#
-
-       movdqu  16*0(arg2), %xmm9
-       movdqu  16*1(arg2), %xmm12
-       pshufb  %xmm11, %xmm9
-       pshufb  %xmm11, %xmm12
-       movdqa  %xmm0, %xmm8
-       movdqa  %xmm1, %xmm13
-       pclmulqdq       $0x0 , %xmm10, %xmm0
-       pclmulqdq       $0x11, %xmm10, %xmm8
-       pclmulqdq       $0x0 , %xmm10, %xmm1
-       pclmulqdq       $0x11, %xmm10, %xmm13
-       pxor    %xmm9 , %xmm0
-       xorps   %xmm8 , %xmm0
-       pxor    %xmm12, %xmm1
-       xorps   %xmm13, %xmm1
-
-       movdqu  16*2(arg2), %xmm9
-       movdqu  16*3(arg2), %xmm12
-       pshufb  %xmm11, %xmm9
-       pshufb  %xmm11, %xmm12
-       movdqa  %xmm2, %xmm8
-       movdqa  %xmm3, %xmm13
-       pclmulqdq       $0x0, %xmm10, %xmm2
-       pclmulqdq       $0x11, %xmm10, %xmm8
-       pclmulqdq       $0x0, %xmm10, %xmm3
-       pclmulqdq       $0x11, %xmm10, %xmm13
-       pxor    %xmm9 , %xmm2
-       xorps   %xmm8 , %xmm2
-       pxor    %xmm12, %xmm3
-       xorps   %xmm13, %xmm3
-
-       movdqu  16*4(arg2), %xmm9
-       movdqu  16*5(arg2), %xmm12
-       pshufb  %xmm11, %xmm9
-       pshufb  %xmm11, %xmm12
-       movdqa  %xmm4, %xmm8
-       movdqa  %xmm5, %xmm13
-       pclmulqdq       $0x0,  %xmm10, %xmm4
-       pclmulqdq       $0x11, %xmm10, %xmm8
-       pclmulqdq       $0x0,  %xmm10, %xmm5
-       pclmulqdq       $0x11, %xmm10, %xmm13
-       pxor    %xmm9 ,  %xmm4
-       xorps   %xmm8 ,  %xmm4
-       pxor    %xmm12,  %xmm5
-       xorps   %xmm13,  %xmm5
-
-       movdqu  16*6(arg2), %xmm9
-       movdqu  16*7(arg2), %xmm12
-       pshufb  %xmm11, %xmm9
-       pshufb  %xmm11, %xmm12
-       movdqa  %xmm6 , %xmm8
-       movdqa  %xmm7 , %xmm13
-       pclmulqdq       $0x0 , %xmm10, %xmm6
-       pclmulqdq       $0x11, %xmm10, %xmm8
-       pclmulqdq       $0x0 , %xmm10, %xmm7
-       pclmulqdq       $0x11, %xmm10, %xmm13
-       pxor    %xmm9 , %xmm6
-       xorps   %xmm8 , %xmm6
-       pxor    %xmm12, %xmm7
-       xorps   %xmm13, %xmm7
-
-       sub     $128, arg3
-
-       # check if there is another 64B in the buffer to be able to fold
-       jge     _fold_64_B_loop
-       ##################################################################
-
-
-       add     $128, arg2
-       # at this point, the buffer pointer is pointing at the last y Bytes
-       # of the buffer the 64B of folded data is in 4 of the xmm
-       # registers: xmm0, xmm1, xmm2, xmm3
-
-
-       # fold the 8 xmm registers to 1 xmm register with different constants
-
-       movdqa  rk9(%rip), %xmm10
-       movdqa  %xmm0, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm0
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       xorps   %xmm0, %xmm7
-
-       movdqa  rk11(%rip), %xmm10
-       movdqa  %xmm1, %xmm8
-       pclmulqdq        $0x11, %xmm10, %xmm1
-       pclmulqdq        $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       xorps   %xmm1, %xmm7
-
-       movdqa  rk13(%rip), %xmm10
-       movdqa  %xmm2, %xmm8
-       pclmulqdq        $0x11, %xmm10, %xmm2
-       pclmulqdq        $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       pxor    %xmm2, %xmm7
-
-       movdqa  rk15(%rip), %xmm10
-       movdqa  %xmm3, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm3
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       xorps   %xmm3, %xmm7
-
-       movdqa  rk17(%rip), %xmm10
-       movdqa  %xmm4, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm4
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       pxor    %xmm4, %xmm7
-
-       movdqa  rk19(%rip), %xmm10
-       movdqa  %xmm5, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm5
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       xorps   %xmm5, %xmm7
-
-       movdqa  rk1(%rip), %xmm10       #xmm10 has rk1 and rk2
-                                       #imm value of pclmulqdq instruction
-                                       #will determine which constant to use
-       movdqa  %xmm6, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm6
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       pxor    %xmm6, %xmm7
-
-
-       # instead of 64, we add 48 to the loop counter to save 1 instruction
-       # from the loop instead of a cmp instruction, we use the negative
-       # flag with the jl instruction
-       add     $128-16, arg3
-       jl      _final_reduction_for_128
-
-       # now we have 16+y bytes left to reduce. 16 Bytes is in register xmm7
-       # and the rest is in memory. We can fold 16 bytes at a time if y>=16
-       # continue folding 16B at a time
-
-_16B_reduction_loop:
-       movdqa  %xmm7, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm7
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       movdqu  (arg2), %xmm0
-       pshufb  %xmm11, %xmm0
-       pxor    %xmm0 , %xmm7
-       add     $16, arg2
-       sub     $16, arg3
-       # instead of a cmp instruction, we utilize the flags with the
-       # jge instruction equivalent of: cmp arg3, 16-16
-       # check if there is any more 16B in the buffer to be able to fold
-       jge     _16B_reduction_loop
-
-       #now we have 16+z bytes left to reduce, where 0<= z < 16.
-       #first, we reduce the data in the xmm7 register
-
-
-_final_reduction_for_128:
-       # check if any more data to fold. If not, compute the CRC of
-       # the final 128 bits
-       add     $16, arg3
-       je      _128_done
-
-       # here we are getting data that is less than 16 bytes.
-       # since we know that there was data before the pointer, we can
-       # offset the input pointer before the actual point, to receive
-       # exactly 16 bytes. after that the registers need to be adjusted.
-_get_last_two_xmms:
-       movdqa  %xmm7, %xmm2
-
-       movdqu  -16(arg2, arg3), %xmm1
-       pshufb  %xmm11, %xmm1
-
-       # get rid of the extra data that was loaded before
-       # load the shift constant
-       lea     pshufb_shf_table+16(%rip), %rax
-       sub     arg3, %rax
-       movdqu  (%rax), %xmm0
-
-       # shift xmm2 to the left by arg3 bytes
-       pshufb  %xmm0, %xmm2
-
-       # shift xmm7 to the right by 16-arg3 bytes
-       pxor    mask1(%rip), %xmm0
-       pshufb  %xmm0, %xmm7
-       pblendvb        %xmm2, %xmm1    #xmm0 is implicit
-
-       # fold 16 Bytes
-       movdqa  %xmm1, %xmm2
-       movdqa  %xmm7, %xmm8
-       pclmulqdq       $0x11, %xmm10, %xmm7
-       pclmulqdq       $0x0 , %xmm10, %xmm8
-       pxor    %xmm8, %xmm7
-       pxor    %xmm2, %xmm7
-
-_128_done:
-       # compute crc of a 128-bit value
-       movdqa  rk5(%rip), %xmm10       # rk5 and rk6 in xmm10
-       movdqa  %xmm7, %xmm0
-
-       #64b fold
-       pclmulqdq       $0x1, %xmm10, %xmm7
-       pslldq  $8   ,  %xmm0
-       pxor    %xmm0,  %xmm7
-
-       #32b fold
-       movdqa  %xmm7, %xmm0
-
-       pand    mask2(%rip), %xmm0
-
-       psrldq  $12, %xmm7
-       pclmulqdq       $0x10, %xmm10, %xmm7
-       pxor    %xmm0, %xmm7
-
-       #barrett reduction
-_barrett:
-       movdqa  rk7(%rip), %xmm10       # rk7 and rk8 in xmm10
-       movdqa  %xmm7, %xmm0
-       pclmulqdq       $0x01, %xmm10, %xmm7
-       pslldq  $4, %xmm7
-       pclmulqdq       $0x11, %xmm10, %xmm7
-
-       pslldq  $4, %xmm7
-       pxor    %xmm0, %xmm7
-       pextrd  $1, %xmm7, %eax
-
-_cleanup:
-       # scale the result back to 16 bits
-       shr     $16, %eax
-       mov     %rcx, %rsp
-       ret
-
-########################################################################
-
-.align 16
-_less_than_128:
-
-       # check if there is enough buffer to be able to fold 16B at a time
-       cmp     $32, arg3
-       jl      _less_than_32
-       movdqa  SHUF_MASK(%rip), %xmm11
-
-       # now if there is, load the constants
-       movdqa  rk1(%rip), %xmm10       # rk1 and rk2 in xmm10
-
-       movd    arg1_low32, %xmm0       # get the initial crc value
-       pslldq  $12, %xmm0      # align it to its correct place
-       movdqu  (arg2), %xmm7   # load the plaintext
-       pshufb  %xmm11, %xmm7   # byte-reflect the plaintext
-       pxor    %xmm0, %xmm7
-
-
-       # update the buffer pointer
-       add     $16, arg2
-
-       # update the counter. subtract 32 instead of 16 to save one
-       # instruction from the loop
-       sub     $32, arg3
-
-       jmp     _16B_reduction_loop
-
-
-.align 16
-_less_than_32:
-       # mov initial crc to the return value. this is necessary for
-       # zero-length buffers.
-       mov     arg1_low32, %eax
-       test    arg3, arg3
-       je      _cleanup
-
-       movdqa  SHUF_MASK(%rip), %xmm11
-
-       movd    arg1_low32, %xmm0       # get the initial crc value
-       pslldq  $12, %xmm0      # align it to its correct place
-
-       cmp     $16, arg3
-       je      _exact_16_left
-       jl      _less_than_16_left
-
-       movdqu  (arg2), %xmm7   # load the plaintext
-       pshufb  %xmm11, %xmm7   # byte-reflect the plaintext
-       pxor    %xmm0 , %xmm7   # xor the initial crc value
-       add     $16, arg2
-       sub     $16, arg3
-       movdqa  rk1(%rip), %xmm10       # rk1 and rk2 in xmm10
-       jmp     _get_last_two_xmms
-
-
-.align 16
-_less_than_16_left:
-       # use stack space to load data less than 16 bytes, zero-out
-       # the 16B in memory first.
-
-       pxor    %xmm1, %xmm1
-       mov     %rsp, %r11
-       movdqa  %xmm1, (%r11)
-
-       cmp     $4, arg3
-       jl      _only_less_than_4
-
-       # backup the counter value
-       mov     arg3, %r9
-       cmp     $8, arg3
-       jl      _less_than_8_left
-
-       # load 8 Bytes
-       mov     (arg2), %rax
-       mov     %rax, (%r11)
-       add     $8, %r11
-       sub     $8, arg3
-       add     $8, arg2
-_less_than_8_left:
-
-       cmp     $4, arg3
-       jl      _less_than_4_left
-
-       # load 4 Bytes
-       mov     (arg2), %eax
-       mov     %eax, (%r11)
-       add     $4, %r11
-       sub     $4, arg3
-       add     $4, arg2
-_less_than_4_left:
-
-       cmp     $2, arg3
-       jl      _less_than_2_left
-
-       # load 2 Bytes
-       mov     (arg2), %ax
-       mov     %ax, (%r11)
-       add     $2, %r11
-       sub     $2, arg3
-       add     $2, arg2
-_less_than_2_left:
-       cmp     $1, arg3
-        jl      _zero_left
-
-       # load 1 Byte
-       mov     (arg2), %al
-       mov     %al, (%r11)
-_zero_left:
-       movdqa  (%rsp), %xmm7
-       pshufb  %xmm11, %xmm7
-       pxor    %xmm0 , %xmm7   # xor the initial crc value
-
-       # shl r9, 4
-       lea     pshufb_shf_table+16(%rip), %rax
-       sub     %r9, %rax
-       movdqu  (%rax), %xmm0
-       pxor    mask1(%rip), %xmm0
-
-       pshufb  %xmm0, %xmm7
-       jmp     _128_done
-
-.align 16
-_exact_16_left:
-       movdqu  (arg2), %xmm7
-       pshufb  %xmm11, %xmm7
-       pxor    %xmm0 , %xmm7   # xor the initial crc value
-
-       jmp     _128_done
-
-_only_less_than_4:
-       cmp     $3, arg3
-       jl      _only_less_than_3
-
-       # load 3 Bytes
-       mov     (arg2), %al
-       mov     %al, (%r11)
-
-       mov     1(arg2), %al
-       mov     %al, 1(%r11)
-
-       mov     2(arg2), %al
-       mov     %al, 2(%r11)
-
-       movdqa   (%rsp), %xmm7
-       pshufb   %xmm11, %xmm7
-       pxor     %xmm0 , %xmm7  # xor the initial crc value
-
-       psrldq  $5, %xmm7
-
-       jmp     _barrett
-_only_less_than_3:
-       cmp     $2, arg3
-       jl      _only_less_than_2
-
-       # load 2 Bytes
-       mov     (arg2), %al
-       mov     %al, (%r11)
-
-       mov     1(arg2), %al
-       mov     %al, 1(%r11)
-
-       movdqa  (%rsp), %xmm7
-       pshufb  %xmm11, %xmm7
-       pxor    %xmm0 , %xmm7   # xor the initial crc value
-
-       psrldq  $6, %xmm7
-
-       jmp     _barrett
-_only_less_than_2:
-
-       # load 1 Byte
-       mov     (arg2), %al
-       mov     %al, (%r11)
-
-       movdqa  (%rsp), %xmm7
-       pshufb  %xmm11, %xmm7
-       pxor    %xmm0 , %xmm7   # xor the initial crc value
-
-       psrldq  $7, %xmm7
-
-       jmp     _barrett
-
-ENDPROC(crc_t10dif_pcl)
-
-.data
-
-# precomputed constants
-# these constants are precomputed from the poly:
-# 0x8bb70000 (0x8bb7 scaled to 32 bits)
-.align 16
-# Q = 0x18BB70000
-# rk1 = 2^(32*3) mod Q << 32
-# rk2 = 2^(32*5) mod Q << 32
-# rk3 = 2^(32*15) mod Q << 32
-# rk4 = 2^(32*17) mod Q << 32
-# rk5 = 2^(32*3) mod Q << 32
-# rk6 = 2^(32*2) mod Q << 32
-# rk7 = floor(2^64/Q)
-# rk8 = Q
-rk1:
-.quad 0x2d56000000000000
-rk2:
-.quad 0x06df000000000000
-rk3:
-.quad 0x9d9d000000000000
-rk4:
-.quad 0x7cf5000000000000
-rk5:
-.quad 0x2d56000000000000
-rk6:
-.quad 0x1368000000000000
-rk7:
-.quad 0x00000001f65a57f8
-rk8:
-.quad 0x000000018bb70000
-
-rk9:
-.quad 0xceae000000000000
-rk10:
-.quad 0xbfd6000000000000
-rk11:
-.quad 0x1e16000000000000
-rk12:
-.quad 0x713c000000000000
-rk13:
-.quad 0xf7f9000000000000
-rk14:
-.quad 0x80a6000000000000
-rk15:
-.quad 0x044c000000000000
-rk16:
-.quad 0xe658000000000000
-rk17:
-.quad 0xad18000000000000
-rk18:
-.quad 0xa497000000000000
-rk19:
-.quad 0x6ee3000000000000
-rk20:
-.quad 0xe7b5000000000000
-
-
-
-mask1:
-.octa 0x80808080808080808080808080808080
-mask2:
-.octa 0x00000000FFFFFFFFFFFFFFFFFFFFFFFF
-
-SHUF_MASK:
-.octa 0x000102030405060708090A0B0C0D0E0F
-
-pshufb_shf_table:
-# use these values for shift constants for the pshufb instruction
-# different alignments result in values as shown:
-#      DDQ 0x008f8e8d8c8b8a898887868584838281 # shl 15 (16-1) / shr1
-#      DDQ 0x01008f8e8d8c8b8a8988878685848382 # shl 14 (16-3) / shr2
-#      DDQ 0x0201008f8e8d8c8b8a89888786858483 # shl 13 (16-4) / shr3
-#      DDQ 0x030201008f8e8d8c8b8a898887868584 # shl 12 (16-4) / shr4
-#      DDQ 0x04030201008f8e8d8c8b8a8988878685 # shl 11 (16-5) / shr5
-#      DDQ 0x0504030201008f8e8d8c8b8a89888786 # shl 10 (16-6) / shr6
-#      DDQ 0x060504030201008f8e8d8c8b8a898887 # shl 9  (16-7) / shr7
-#      DDQ 0x07060504030201008f8e8d8c8b8a8988 # shl 8  (16-8) / shr8
-#      DDQ 0x0807060504030201008f8e8d8c8b8a89 # shl 7  (16-9) / shr9
-#      DDQ 0x090807060504030201008f8e8d8c8b8a # shl 6  (16-10) / shr10
-#      DDQ 0x0a090807060504030201008f8e8d8c8b # shl 5  (16-11) / shr11
-#      DDQ 0x0b0a090807060504030201008f8e8d8c # shl 4  (16-12) / shr12
-#      DDQ 0x0c0b0a090807060504030201008f8e8d # shl 3  (16-13) / shr13
-#      DDQ 0x0d0c0b0a090807060504030201008f8e # shl 2  (16-14) / shr14
-#      DDQ 0x0e0d0c0b0a090807060504030201008f # shl 1  (16-15) / shr15
-.octa 0x8f8e8d8c8b8a89888786858483828100
-.octa 0x000e0d0c0b0a09080706050403020100
diff --git a/arch/x86/crypto/crct10dif-pclmul_glue.c b/arch/x86/crypto/crct10dif-pclmul_glue.c
deleted file mode 100644 (file)
index 7845d7f..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Cryptographic API.
- *
- * T10 Data Integrity Field CRC16 Crypto Transform using PCLMULQDQ Instructions
- *
- * Copyright (C) 2013 Intel Corporation
- * Author: Tim Chen <tim.c.chen@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/crc-t10dif.h>
-#include <crypto/internal/hash.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <asm/i387.h>
-#include <asm/cpufeature.h>
-#include <asm/cpu_device_id.h>
-
-asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf,
-                               size_t len);
-
-struct chksum_desc_ctx {
-       __u16 crc;
-};
-
-/*
- * Steps through buffer one byte at at time, calculates reflected
- * crc using table.
- */
-
-static int chksum_init(struct shash_desc *desc)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       ctx->crc = 0;
-
-       return 0;
-}
-
-static int chksum_update(struct shash_desc *desc, const u8 *data,
-                        unsigned int length)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       if (irq_fpu_usable()) {
-               kernel_fpu_begin();
-               ctx->crc = crc_t10dif_pcl(ctx->crc, data, length);
-               kernel_fpu_end();
-       } else
-               ctx->crc = crc_t10dif_generic(ctx->crc, data, length);
-       return 0;
-}
-
-static int chksum_final(struct shash_desc *desc, u8 *out)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       *(__u16 *)out = ctx->crc;
-       return 0;
-}
-
-static int __chksum_finup(__u16 *crcp, const u8 *data, unsigned int len,
-                       u8 *out)
-{
-       if (irq_fpu_usable()) {
-               kernel_fpu_begin();
-               *(__u16 *)out = crc_t10dif_pcl(*crcp, data, len);
-               kernel_fpu_end();
-       } else
-               *(__u16 *)out = crc_t10dif_generic(*crcp, data, len);
-       return 0;
-}
-
-static int chksum_finup(struct shash_desc *desc, const u8 *data,
-                       unsigned int len, u8 *out)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       return __chksum_finup(&ctx->crc, data, len, out);
-}
-
-static int chksum_digest(struct shash_desc *desc, const u8 *data,
-                        unsigned int length, u8 *out)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       return __chksum_finup(&ctx->crc, data, length, out);
-}
-
-static struct shash_alg alg = {
-       .digestsize             =       CRC_T10DIF_DIGEST_SIZE,
-       .init           =       chksum_init,
-       .update         =       chksum_update,
-       .final          =       chksum_final,
-       .finup          =       chksum_finup,
-       .digest         =       chksum_digest,
-       .descsize               =       sizeof(struct chksum_desc_ctx),
-       .base                   =       {
-               .cra_name               =       "crct10dif",
-               .cra_driver_name        =       "crct10dif-pclmul",
-               .cra_priority           =       200,
-               .cra_blocksize          =       CRC_T10DIF_BLOCK_SIZE,
-               .cra_module             =       THIS_MODULE,
-       }
-};
-
-static const struct x86_cpu_id crct10dif_cpu_id[] = {
-       X86_FEATURE_MATCH(X86_FEATURE_PCLMULQDQ),
-       {}
-};
-MODULE_DEVICE_TABLE(x86cpu, crct10dif_cpu_id);
-
-static int __init crct10dif_intel_mod_init(void)
-{
-       if (!x86_match_cpu(crct10dif_cpu_id))
-               return -ENODEV;
-
-       return crypto_register_shash(&alg);
-}
-
-static void __exit crct10dif_intel_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_init(crct10dif_intel_mod_init);
-module_exit(crct10dif_intel_mod_fini);
-
-MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>");
-MODULE_DESCRIPTION("T10 DIF CRC calculation accelerated with PCLMULQDQ.");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("crct10dif");
-MODULE_ALIAS("crct10dif-pclmul");
index 69ce573f1224560b4f5c7532e21053b27c651da4..aca01164f00200a8d14efa8a82e4a400b67d0bf1 100644 (file)
@@ -376,25 +376,6 @@ config CRYPTO_CRC32_PCLMUL
          which will enable any routine to use the CRC-32-IEEE 802.3 checksum
          and gain better performance as compared with the table implementation.
 
-config CRYPTO_CRCT10DIF
-       tristate "CRCT10DIF algorithm"
-       select CRYPTO_HASH
-       help
-         CRC T10 Data Integrity Field computation is being cast as
-         a crypto transform.  This allows for faster crc t10 diff
-         transforms to be used if they are available.
-
-config CRYPTO_CRCT10DIF_PCLMUL
-       tristate "CRCT10DIF PCLMULQDQ hardware acceleration"
-       depends on X86 && 64BIT && CRC_T10DIF
-       select CRYPTO_HASH
-       help
-         For x86_64 processors with SSE4.2 and PCLMULQDQ supported,
-         CRC T10 DIF PCLMULQDQ computation can be hardware
-         accelerated PCLMULQDQ instruction. This option will create
-         'crct10dif-plcmul' module, which is faster when computing the
-         crct10dif checksum as compared with the generic table implementation.
-
 config CRYPTO_GHASH
        tristate "GHASH digest algorithm"
        select CRYPTO_GF128MUL
index 2d5ed08a239fa3e79110c9dfd077d30da8954192..2ba0df2f908f5985ef23f0794c1f49e6fd5f3720 100644 (file)
@@ -83,7 +83,6 @@ obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 obj-$(CONFIG_CRYPTO_CRC32) += crc32.o
-obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
 obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
diff --git a/crypto/crct10dif.c b/crypto/crct10dif.c
deleted file mode 100644 (file)
index 92aca96..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Cryptographic API.
- *
- * T10 Data Integrity Field CRC16 Crypto Transform
- *
- * Copyright (c) 2007 Oracle Corporation.  All rights reserved.
- * Written by Martin K. Petersen <martin.petersen@oracle.com>
- * Copyright (C) 2013 Intel Corporation
- * Author: Tim Chen <tim.c.chen@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/crc-t10dif.h>
-#include <crypto/internal/hash.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-struct chksum_desc_ctx {
-       __u16 crc;
-};
-
-/* Table generated using the following polynomium:
- * x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
- * gt: 0x8bb7
- */
-static const __u16 t10_dif_crc_table[256] = {
-       0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B,
-       0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6,
-       0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6,
-       0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B,
-       0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1,
-       0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C,
-       0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C,
-       0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781,
-       0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8,
-       0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255,
-       0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925,
-       0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698,
-       0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472,
-       0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF,
-       0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF,
-       0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02,
-       0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA,
-       0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067,
-       0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17,
-       0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA,
-       0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640,
-       0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD,
-       0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D,
-       0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30,
-       0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759,
-       0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4,
-       0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394,
-       0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29,
-       0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3,
-       0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E,
-       0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E,
-       0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3
-};
-
-__u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, size_t len)
-{
-       unsigned int i;
-
-       for (i = 0 ; i < len ; i++)
-               crc = (crc << 8) ^ t10_dif_crc_table[((crc >> 8) ^ buffer[i]) & 0xff];
-
-       return crc;
-}
-EXPORT_SYMBOL(crc_t10dif_generic);
-
-/*
- * Steps through buffer one byte at at time, calculates reflected
- * crc using table.
- */
-
-static int chksum_init(struct shash_desc *desc)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       ctx->crc = 0;
-
-       return 0;
-}
-
-static int chksum_update(struct shash_desc *desc, const u8 *data,
-                        unsigned int length)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       ctx->crc = crc_t10dif_generic(ctx->crc, data, length);
-       return 0;
-}
-
-static int chksum_final(struct shash_desc *desc, u8 *out)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       *(__u16 *)out = ctx->crc;
-       return 0;
-}
-
-static int __chksum_finup(__u16 *crcp, const u8 *data, unsigned int len,
-                       u8 *out)
-{
-       *(__u16 *)out = crc_t10dif_generic(*crcp, data, len);
-       return 0;
-}
-
-static int chksum_finup(struct shash_desc *desc, const u8 *data,
-                       unsigned int len, u8 *out)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       return __chksum_finup(&ctx->crc, data, len, out);
-}
-
-static int chksum_digest(struct shash_desc *desc, const u8 *data,
-                        unsigned int length, u8 *out)
-{
-       struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
-
-       return __chksum_finup(&ctx->crc, data, length, out);
-}
-
-static struct shash_alg alg = {
-       .digestsize             =       CRC_T10DIF_DIGEST_SIZE,
-       .init           =       chksum_init,
-       .update         =       chksum_update,
-       .final          =       chksum_final,
-       .finup          =       chksum_finup,
-       .digest         =       chksum_digest,
-       .descsize               =       sizeof(struct chksum_desc_ctx),
-       .base                   =       {
-               .cra_name               =       "crct10dif",
-               .cra_driver_name        =       "crct10dif-generic",
-               .cra_priority           =       100,
-               .cra_blocksize          =       CRC_T10DIF_BLOCK_SIZE,
-               .cra_module             =       THIS_MODULE,
-       }
-};
-
-static int __init crct10dif_mod_init(void)
-{
-       int ret;
-
-       ret = crypto_register_shash(&alg);
-       return ret;
-}
-
-static void __exit crct10dif_mod_fini(void)
-{
-       crypto_unregister_shash(&alg);
-}
-
-module_init(crct10dif_mod_init);
-module_exit(crct10dif_mod_fini);
-
-MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>");
-MODULE_DESCRIPTION("T10 DIF CRC calculation.");
-MODULE_LICENSE("GPL");
index 25a5934f0e50a011f73db08a84735ae76b2a7f60..66d254ce0d11b35ca55e07b8b0fd786c0b0f0c10 100644 (file)
@@ -1174,10 +1174,6 @@ static int do_test(int m)
                ret += tcrypt_test("ghash");
                break;
 
-       case 47:
-               ret += tcrypt_test("crct10dif");
-               break;
-
        case 100:
                ret += tcrypt_test("hmac(md5)");
                break;
@@ -1502,10 +1498,6 @@ static int do_test(int m)
                test_hash_speed("crc32c", sec, generic_hash_speed_template);
                if (mode > 300 && mode < 400) break;
 
-       case 320:
-               test_hash_speed("crct10dif", sec, generic_hash_speed_template);
-               if (mode > 300 && mode < 400) break;
-
        case 399:
                break;
 
index 2f00607039e2ad7c808d273f08756a8e463732d4..ecddf921a9db401ee30bea1bf24b30f0ee8dd85d 100644 (file)
@@ -2045,16 +2045,6 @@ static const struct alg_test_desc alg_test_descs[] = {
                                .count = CRC32C_TEST_VECTORS
                        }
                }
-       }, {
-               .alg = "crct10dif",
-               .test = alg_test_hash,
-               .fips_allowed = 1,
-               .suite = {
-                       .hash = {
-                               .vecs = crct10dif_tv_template,
-                               .count = CRCT10DIF_TEST_VECTORS
-                       }
-               }
        }, {
                .alg = "cryptd(__driver-cbc-aes-aesni)",
                .test = alg_test_null,
index 7d44aa3d6b4472646dd9b93a77d97a0a58762eae..1e701bc075b907521c0e0cd4a06e41858cda0a5f 100644 (file)
@@ -450,39 +450,6 @@ static struct hash_testvec rmd320_tv_template[] = {
        }
 };
 
-#define CRCT10DIF_TEST_VECTORS 3
-static struct hash_testvec crct10dif_tv_template[] = {
-       {
-               .plaintext = "abc",
-               .psize  = 3,
-#ifdef __LITTLE_ENDIAN
-               .digest = "\x3b\x44",
-#else
-               .digest = "\x44\x3b",
-#endif
-       }, {
-               .plaintext = "1234567890123456789012345678901234567890"
-                            "123456789012345678901234567890123456789",
-               .psize  = 79,
-#ifdef __LITTLE_ENDIAN
-               .digest = "\x70\x4b",
-#else
-               .digest = "\x4b\x70",
-#endif
-       }, {
-               .plaintext =
-               "abcddddddddddddddddddddddddddddddddddddddddddddddddddddd",
-               .psize  = 56,
-#ifdef __LITTLE_ENDIAN
-               .digest = "\xe3\x9c",
-#else
-               .digest = "\x9c\xe3",
-#endif
-               .np     = 2,
-               .tap    = { 28, 28 }
-       }
-};
-
 /*
  * SHA1 test vectors  from from FIPS PUB 180-1
  * Long vector from CAVS 5.0
index 227aca77ee1ef7777277d34a4b5e5774efa1286e..5da44e81dd4d70f7ed42ae1f1587734c0b6a5a55 100644 (file)
@@ -169,10 +169,8 @@ int acpi_create_platform_device(struct acpi_device *adev,
   -------------------------------------------------------------------------- */
 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
 bool acpi_video_backlight_quirks(void);
-bool acpi_video_verify_backlight_support(void);
 #else
 static inline bool acpi_video_backlight_quirks(void) { return false; }
-static inline bool acpi_video_verify_backlight_support(void) { return false; }
 #endif
 
 #endif /* _ACPI_INTERNAL_H_ */
index 6dd237e79b4f977e2f8c2a934303fd5e46d13690..0ec434d2586da29d65003aed0b7d9c7dd244944e 100644 (file)
@@ -911,7 +911,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
        if (acpi_video_init_brightness(device))
                return;
 
-       if (acpi_video_verify_backlight_support()) {
+       if (acpi_video_backlight_support()) {
                struct backlight_properties props;
                struct pci_dev *pdev;
                acpi_handle acpi_parent;
@@ -1366,8 +1366,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
        unsigned long long level_current, level_next;
        int result = -EINVAL;
 
-       /* no warning message if acpi_backlight=vendor or a quirk is used */
-       if (!acpi_video_verify_backlight_support())
+       /* no warning message if acpi_backlight=vendor is used */
+       if (!acpi_video_backlight_support())
                return 0;
 
        if (!device->brightness)
@@ -1875,46 +1875,6 @@ static int acpi_video_bus_remove(struct acpi_device *device)
        return 0;
 }
 
-static acpi_status video_unregister_backlight(acpi_handle handle, u32 lvl,
-                                             void *context, void **rv)
-{
-       struct acpi_device *acpi_dev;
-       struct acpi_video_bus *video;
-       struct acpi_video_device *dev, *next;
-
-       if (acpi_bus_get_device(handle, &acpi_dev))
-               return AE_OK;
-
-       if (acpi_match_device_ids(acpi_dev, video_device_ids))
-               return AE_OK;
-
-       video = acpi_driver_data(acpi_dev);
-       if (!video)
-               return AE_OK;
-
-       acpi_video_bus_stop_devices(video);
-       mutex_lock(&video->device_list_lock);
-       list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
-               if (dev->backlight) {
-                       backlight_device_unregister(dev->backlight);
-                       dev->backlight = NULL;
-                       kfree(dev->brightness->levels);
-                       kfree(dev->brightness);
-               }
-               if (dev->cooling_dev) {
-                       sysfs_remove_link(&dev->dev->dev.kobj,
-                                         "thermal_cooling");
-                       sysfs_remove_link(&dev->cooling_dev->device.kobj,
-                                         "device");
-                       thermal_cooling_device_unregister(dev->cooling_dev);
-                       dev->cooling_dev = NULL;
-               }
-       }
-       mutex_unlock(&video->device_list_lock);
-       acpi_video_bus_start_devices(video);
-       return AE_OK;
-}
-
 static int __init is_i740(struct pci_dev *dev)
 {
        if (dev->device == 0x00D1)
@@ -1946,25 +1906,14 @@ static int __init intel_opregion_present(void)
        return opregion;
 }
 
-int __acpi_video_register(bool backlight_quirks)
+int acpi_video_register(void)
 {
-       bool no_backlight;
-       int result;
-
-       no_backlight = backlight_quirks ? acpi_video_backlight_quirks() : false;
-
+       int result = 0;
        if (register_count) {
                /*
-                * If acpi_video_register() has been called already, don't try
-                * to register acpi_video_bus, but unregister backlight devices
-                * if no backlight support is requested.
+                * if the function of acpi_video_register is already called,
+                * don't register the acpi_vide_bus again and return no error.
                 */
-               if (no_backlight)
-                       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                                           ACPI_UINT32_MAX,
-                                           video_unregister_backlight,
-                                           NULL, NULL, NULL);
-
                return 0;
        }
 
@@ -1980,7 +1929,7 @@ int __acpi_video_register(bool backlight_quirks)
 
        return 0;
 }
-EXPORT_SYMBOL(__acpi_video_register);
+EXPORT_SYMBOL(acpi_video_register);
 
 void acpi_video_unregister(void)
 {
index 826e52def08074bad91038ad25df387917b690ec..c3397748ba466ca13f41c664b4c374c7dea5d028 100644 (file)
@@ -238,12 +238,7 @@ static void acpi_video_caps_check(void)
 
 bool acpi_video_backlight_quirks(void)
 {
-       if (acpi_gbl_osi_data >= ACPI_OSI_WIN_8) {
-               acpi_video_caps_check();
-               acpi_video_support |= ACPI_VIDEO_SKIP_BACKLIGHT;
-               return true;
-       }
-       return false;
+       return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
 }
 EXPORT_SYMBOL(acpi_video_backlight_quirks);
 
@@ -291,14 +286,6 @@ int acpi_video_backlight_support(void)
 }
 EXPORT_SYMBOL(acpi_video_backlight_support);
 
-/* For the ACPI video driver use only. */
-bool acpi_video_verify_backlight_support(void)
-{
-       return (acpi_video_support & ACPI_VIDEO_SKIP_BACKLIGHT) ?
-               false : acpi_video_backlight_support();
-}
-EXPORT_SYMBOL(acpi_video_verify_backlight_support);
-
 /*
  * Use acpi_backlight=vendor/video to force that backlight switching
  * is processed by vendor specific acpi drivers or video.ko driver.
index 80dc988f01e4f1eebb7d12311ab98c8ac48dc013..4e737728aee207a5d644d6fa0d39b0e3c402bd47 100644 (file)
@@ -97,6 +97,15 @@ config SATA_AHCI_PLATFORM
 
          If unsure, say N.
 
+config AHCI_IMX
+       tristate "Freescale i.MX AHCI SATA support"
+       depends on SATA_AHCI_PLATFORM && MFD_SYSCON
+       help
+         This option enables support for the Freescale i.MX SoC's
+         onboard AHCI SATA.
+
+         If unsure, say N.
+
 config SATA_FSL
        tristate "Freescale 3.0Gbps SATA support"
        depends on FSL_SOC
@@ -107,7 +116,7 @@ config SATA_FSL
          If unsure, say N.
 
 config SATA_INIC162X
-       tristate "Initio 162x SATA support"
+       tristate "Initio 162x SATA support (Very Experimental)"
        depends on PCI
        help
          This option enables support for Initio 162x Serial ATA.
index c04d0fd038a312485712ed2be8a42d77b32df5c9..46518c622460942cdf8e2971dd95f3b069961ada 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_SATA_INIC162X)   += sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)       += sata_sil24.o
 obj-$(CONFIG_SATA_DWC)         += sata_dwc_460ex.o
 obj-$(CONFIG_SATA_HIGHBANK)    += sata_highbank.o libahci.o
+obj-$(CONFIG_AHCI_IMX)         += ahci_imx.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)         += pdc_adma.o
index 5064f3ea20f1b6f362928bd7a5b3cce39894b259..db4380d7003115ef8c4d05c1ca3543adce0efecb 100644 (file)
@@ -1146,11 +1146,18 @@ int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
                return rc;
 
        for (i = 0; i < host->n_ports; i++) {
+               const char* desc;
                struct ahci_port_priv *pp = host->ports[i]->private_data;
 
+               /* pp is NULL for dummy ports */
+               if (pp)
+                       desc = pp->irq_desc;
+               else
+                       desc = dev_driver_string(host->dev);
+
                rc = devm_request_threaded_irq(host->dev,
                        irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
-                       pp->irq_desc, host->ports[i]);
+                       desc, host->ports[i]);
                if (rc)
                        goto out_free_irqs;
        }
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
new file mode 100644 (file)
index 0000000..58debb0
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Freescale IMX AHCI SATA platform driver
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/ahci_platform.h>
+#include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include "ahci.h"
+
+enum {
+       HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+};
+
+struct imx_ahci_priv {
+       struct platform_device *ahci_pdev;
+       struct clk *sata_ref_clk;
+       struct clk *ahb_clk;
+       struct regmap *gpr;
+};
+
+static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
+{
+       int ret = 0;
+       unsigned int reg_val;
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+
+       imxpriv->gpr =
+               syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+       if (IS_ERR(imxpriv->gpr)) {
+               dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n");
+               return PTR_ERR(imxpriv->gpr);
+       }
+
+       ret = clk_prepare_enable(imxpriv->sata_ref_clk);
+       if (ret < 0) {
+               dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret);
+               return ret;
+       }
+
+       /*
+        * set PHY Paremeters, two steps to configure the GPR13,
+        * one write for rest of parameters, mask of first write
+        * is 0x07fffffd, and the other one write for setting
+        * the mpll_clk_en.
+        */
+       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
+                       | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK
+                       | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK
+                       | IMX6Q_GPR13_SATA_SPD_MODE_MASK
+                       | IMX6Q_GPR13_SATA_MPLL_SS_EN
+                       | IMX6Q_GPR13_SATA_TX_ATTEN_MASK
+                       | IMX6Q_GPR13_SATA_TX_BOOST_MASK
+                       | IMX6Q_GPR13_SATA_TX_LVL_MASK
+                       | IMX6Q_GPR13_SATA_TX_EDGE_RATE
+                       , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
+                       | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
+                       | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F
+                       | IMX6Q_GPR13_SATA_SPD_MODE_3P0G
+                       | IMX6Q_GPR13_SATA_MPLL_SS_EN
+                       | IMX6Q_GPR13_SATA_TX_ATTEN_9_16
+                       | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB
+                       | IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
+       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+                       IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+       usleep_range(100, 200);
+
+       /*
+        * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
+        * and IP vendor specific register HOST_TIMER1MS.
+        * Configure CAP_SSS (support stagered spin up).
+        * Implement the port0.
+        * Get the ahb clock rate, and configure the TIMER1MS register.
+        */
+       reg_val = readl(mmio + HOST_CAP);
+       if (!(reg_val & HOST_CAP_SSS)) {
+               reg_val |= HOST_CAP_SSS;
+               writel(reg_val, mmio + HOST_CAP);
+       }
+       reg_val = readl(mmio + HOST_PORTS_IMPL);
+       if (!(reg_val & 0x1)) {
+               reg_val |= 0x1;
+               writel(reg_val, mmio + HOST_PORTS_IMPL);
+       }
+
+       reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
+       writel(reg_val, mmio + HOST_TIMER1MS);
+
+       return 0;
+}
+
+static void imx6q_sata_exit(struct device *dev)
+{
+       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+
+       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+                       !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+       clk_disable_unprepare(imxpriv->sata_ref_clk);
+}
+
+static struct ahci_platform_data imx6q_sata_pdata = {
+       .init = imx6q_sata_init,
+       .exit = imx6q_sata_exit,
+};
+
+static const struct of_device_id imx_ahci_of_match[] = {
+       { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata},
+       {},
+};
+MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
+
+static int imx_ahci_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct resource *mem, *irq, res[2];
+       const struct of_device_id *of_id;
+       const struct ahci_platform_data *pdata = NULL;
+       struct imx_ahci_priv *imxpriv;
+       struct device *ahci_dev;
+       struct platform_device *ahci_pdev;
+       int ret;
+
+       imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
+       if (!imxpriv) {
+               dev_err(dev, "can't alloc ahci_host_priv\n");
+               return -ENOMEM;
+       }
+
+       ahci_pdev = platform_device_alloc("ahci", -1);
+       if (!ahci_pdev)
+               return -ENODEV;
+
+       ahci_dev = &ahci_pdev->dev;
+       ahci_dev->parent = dev;
+
+       imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
+       if (IS_ERR(imxpriv->ahb_clk)) {
+               dev_err(dev, "can't get ahb clock.\n");
+               ret = PTR_ERR(imxpriv->ahb_clk);
+               goto err_out;
+       }
+
+       imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
+       if (IS_ERR(imxpriv->sata_ref_clk)) {
+               dev_err(dev, "can't get sata_ref clock.\n");
+               ret = PTR_ERR(imxpriv->sata_ref_clk);
+               goto err_out;
+       }
+
+       imxpriv->ahci_pdev = ahci_pdev;
+       platform_set_drvdata(pdev, imxpriv);
+
+       of_id = of_match_device(imx_ahci_of_match, dev);
+       if (of_id) {
+               pdata = of_id->data;
+       } else {
+               ret = -EINVAL;
+               goto err_out;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!mem || !irq) {
+               dev_err(dev, "no mmio/irq resource\n");
+               ret = -ENOMEM;
+               goto err_out;
+       }
+
+       res[0] = *mem;
+       res[1] = *irq;
+
+       ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
+       ahci_dev->of_node = dev->of_node;
+
+       ret = platform_device_add_resources(ahci_pdev, res, 2);
+       if (ret)
+               goto err_out;
+
+       ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata));
+       if (ret)
+               goto err_out;
+
+       ret = platform_device_add(ahci_pdev);
+       if (ret) {
+err_out:
+               platform_device_put(ahci_pdev);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int imx_ahci_remove(struct platform_device *pdev)
+{
+       struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev);
+       struct platform_device *ahci_pdev = imxpriv->ahci_pdev;
+
+       platform_device_unregister(ahci_pdev);
+       return 0;
+}
+
+static struct platform_driver imx_ahci_driver = {
+       .probe = imx_ahci_probe,
+       .remove = imx_ahci_remove,
+       .driver = {
+               .name = "ahci-imx",
+               .owner = THIS_MODULE,
+               .of_match_table = imx_ahci_of_match,
+       },
+};
+module_platform_driver(imx_ahci_driver);
+
+MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
+MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ahci:imx");
index b52a10c8eeb9b775cd1c7fd438ace85571e2ca27..513ad7ed0c997e19c3b3c4190b09221199c3d16c 100644 (file)
@@ -330,7 +330,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
        /* SATA Controller IDE (Wellsburg) */
        { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
-       { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
        { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
        /* SATA Controller IDE (Wellsburg) */
index 83c08907e0428bd44c6fad7f1f634357ea5606cd..b1e880a3c3dabb9b5bd253da522c8879632d993c 100644 (file)
@@ -206,8 +206,10 @@ static ssize_t ata_scsi_park_store(struct device *device,
        unsigned long flags;
        int rc;
 
-       rc = strict_strtol(buf, 10, &input);
-       if (rc || input < -2)
+       rc = kstrtol(buf, 10, &input);
+       if (rc)
+               return rc;
+       if (input < -2)
                return -EINVAL;
        if (input > ATA_TMOUT_MAX_PARK) {
                rc = -EOVERFLOW;
index e4513174824830fa67d3e000ec97a449245fb0c8..5c54d957370afcaf9cf6c0d1962d87cc1b98eaac 100644 (file)
@@ -6,6 +6,18 @@
  *
  * This file is released under GPL v2.
  *
+ * **** WARNING ****
+ *
+ * This driver never worked properly and unfortunately data corruption is
+ * relatively common.  There isn't anyone working on the driver and there's
+ * no support from the vendor.  Do not use this driver in any production
+ * environment.
+ *
+ * http://thread.gmane.org/gmane.linux.debian.devel.bugs.rc/378525/focus=54491
+ * https://bugzilla.kernel.org/show_bug.cgi?id=60565
+ *
+ * *****************
+ *
  * This controller is eccentric and easily locks up if something isn't
  * right.  Documentation is available at initio's website but it only
  * documents registers (not programming model).
@@ -807,6 +819,8 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        ata_print_version_once(&pdev->dev, DRV_VERSION);
 
+       dev_alert(&pdev->dev, "inic162x support is broken with common data corruption issues and will be disabled by default, contact linux-ide@vger.kernel.org if in production use\n");
+
        /* alloc host */
        host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS);
        hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
index b012d7600e1a6c4d29038ba0df98940774cf6b3e..7cde885011ed3d1b15809f6d25c1a7f3ddc3adf1 100644 (file)
@@ -103,10 +103,10 @@ struct pstate_adjust_policy {
 static struct pstate_adjust_policy default_policy = {
        .sample_rate_ms = 10,
        .deadband = 0,
-       .setpoint = 109,
-       .p_gain_pct = 17,
+       .setpoint = 97,
+       .p_gain_pct = 20,
        .d_gain_pct = 0,
-       .i_gain_pct = 4,
+       .i_gain_pct = 0,
 };
 
 struct perf_limits {
@@ -468,12 +468,12 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
        int32_t busy_scaled;
-       int32_t core_busy, turbo_pstate, current_pstate;
+       int32_t core_busy, max_pstate, current_pstate;
 
        core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy);
-       turbo_pstate = int_tofp(cpu->pstate.turbo_pstate);
+       max_pstate = int_tofp(cpu->pstate.max_pstate);
        current_pstate = int_tofp(cpu->pstate.current_pstate);
-       busy_scaled = mul_fp(core_busy, div_fp(turbo_pstate, current_pstate));
+       busy_scaled = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 
        return fp_toint(busy_scaled);
 }
index 5996521a1caff11068e9b2e1e417cdf729f474df..84573b4d6f92809d5cd98fa968f6dd1a617482d3 100644 (file)
@@ -429,7 +429,7 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
        dma_addr_t src_dma, dst_dma;
        int ret = 0;
 
-       desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+       desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
        if (!desc) {
                dev_err(jrdev, "unable to allocate key input memory\n");
                return -ENOMEM;
index 27e86d93826280a62744a559332bf0cd9bc03b3b..89e109022d78a27cf506d995c1c16de2feffea0f 100644 (file)
@@ -48,6 +48,8 @@ static LIST_HEAD(mc_devices);
  */
 static void const *edac_mc_owner;
 
+static struct bus_type mc_bus[EDAC_MAX_MCS];
+
 unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,
                                 unsigned len)
 {
@@ -723,6 +725,11 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
        int ret = -EINVAL;
        edac_dbg(0, "\n");
 
+       if (mci->mc_idx >= EDAC_MAX_MCS) {
+               pr_warn_once("Too many memory controllers: %d\n", mci->mc_idx);
+               return -ENODEV;
+       }
+
 #ifdef CONFIG_EDAC_DEBUG
        if (edac_debug_level >= 3)
                edac_mc_dump_mci(mci);
@@ -762,6 +769,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
        /* set load time so that error rate can be tracked */
        mci->start_time = jiffies;
 
+       mci->bus = &mc_bus[mci->mc_idx];
+
        if (edac_create_sysfs_mci_device(mci)) {
                edac_mc_printk(mci, KERN_WARNING,
                        "failed to create sysfs device\n");
index ef15a7e613bc6b1d1feec75733a86e20cb23efa7..e7c32c4f783737962b575a232f03b5ed19d3629b 100644 (file)
@@ -370,7 +370,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
                return -ENODEV;
 
        csrow->dev.type = &csrow_attr_type;
-       csrow->dev.bus = &mci->bus;
+       csrow->dev.bus = mci->bus;
        device_initialize(&csrow->dev);
        csrow->dev.parent = &mci->dev;
        csrow->mci = mci;
@@ -605,7 +605,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci,
        dimm->mci = mci;
 
        dimm->dev.type = &dimm_attr_type;
-       dimm->dev.bus = &mci->bus;
+       dimm->dev.bus = mci->bus;
        device_initialize(&dimm->dev);
 
        dimm->dev.parent = &mci->dev;
@@ -975,11 +975,13 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
         * The memory controller needs its own bus, in order to avoid
         * namespace conflicts at /sys/bus/edac.
         */
-       mci->bus.name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
-       if (!mci->bus.name)
+       mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
+       if (!mci->bus->name)
                return -ENOMEM;
-       edac_dbg(0, "creating bus %s\n", mci->bus.name);
-       err = bus_register(&mci->bus);
+
+       edac_dbg(0, "creating bus %s\n", mci->bus->name);
+
+       err = bus_register(mci->bus);
        if (err < 0)
                return err;
 
@@ -988,7 +990,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
        device_initialize(&mci->dev);
 
        mci->dev.parent = mci_pdev;
-       mci->dev.bus = &mci->bus;
+       mci->dev.bus = mci->bus;
        dev_set_name(&mci->dev, "mc%d", mci->mc_idx);
        dev_set_drvdata(&mci->dev, mci);
        pm_runtime_forbid(&mci->dev);
@@ -997,8 +999,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
        err = device_add(&mci->dev);
        if (err < 0) {
                edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
-               bus_unregister(&mci->bus);
-               kfree(mci->bus.name);
+               bus_unregister(mci->bus);
+               kfree(mci->bus->name);
                return err;
        }
 
@@ -1064,8 +1066,8 @@ fail:
        }
 fail2:
        device_unregister(&mci->dev);
-       bus_unregister(&mci->bus);
-       kfree(mci->bus.name);
+       bus_unregister(mci->bus);
+       kfree(mci->bus->name);
        return err;
 }
 
@@ -1098,8 +1100,8 @@ void edac_unregister_sysfs(struct mem_ctl_info *mci)
 {
        edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
        device_unregister(&mci->dev);
-       bus_unregister(&mci->bus);
-       kfree(mci->bus.name);
+       bus_unregister(mci->bus);
+       kfree(mci->bus->name);
 }
 
 static void mc_attr_release(struct device *dev)
index 1b635178cc44ff31b8ed224560ebdf86851165f0..157b934e8ce3a528468e45a735ab41dee6043cea 100644 (file)
@@ -974,7 +974,7 @@ static int i5100_setup_debugfs(struct mem_ctl_info *mci)
        if (!i5100_debugfs)
                return -ENODEV;
 
-       priv->debugfs = debugfs_create_dir(mci->bus.name, i5100_debugfs);
+       priv->debugfs = debugfs_create_dir(mci->bus->name, i5100_debugfs);
 
        if (!priv->debugfs)
                return -ENOMEM;
index 05756f95be7cae521b3ad6dcac56307698217d7c..f44c1a004f95e8d1c2bf9719fa0a4f131e6139b8 100644 (file)
@@ -1643,7 +1643,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (INTEL_INFO(dev)->num_pipes) {
                /* Must be done after probing outputs */
                intel_opregion_init(dev);
-               acpi_video_register_with_quirks();
+               acpi_video_register();
        }
 
        if (IS_GEN5(dev))
index af18da76c04b0ceae107c0294ac41577978420b1..044d11d0594423bc47b59317f079999a8bb958e2 100644 (file)
@@ -785,10 +785,22 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
        }
 }
 
+static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
+{
+       struct drm_device *dev = intel_hdmi_to_dev(hdmi);
+
+       if (IS_G4X(dev))
+               return 165000;
+       else if (IS_HASWELL(dev))
+               return 300000;
+       else
+               return 225000;
+}
+
 static int intel_hdmi_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
-       if (mode->clock > 165000)
+       if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector)))
                return MODE_CLOCK_HIGH;
        if (mode->clock < 20000)
                return MODE_CLOCK_LOW;
@@ -806,6 +818,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
        int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2;
+       int portclock_limit = hdmi_portclock_limit(intel_hdmi);
        int desired_bpp;
 
        if (intel_hdmi->color_range_auto) {
@@ -829,7 +842,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
         * outputs. We also need to check that the higher clock still fits
         * within limits.
         */
-       if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= 225000
+       if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit
            && HAS_PCH_SPLIT(dev)) {
                DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
                desired_bpp = 12*3;
@@ -846,7 +859,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
                pipe_config->pipe_bpp = desired_bpp;
        }
 
-       if (adjusted_mode->clock > 225000) {
+       if (adjusted_mode->clock > portclock_limit) {
                DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n");
                return false;
        }
index 93c2f2cceb5165c25e80c6480c60c3e2e9e7fd62..eb89653a7a1710adf2842a2d2fb811cbe6c62737 100644 (file)
@@ -179,9 +179,10 @@ qxl_push_command_ring_release(struct qxl_device *qdev, struct qxl_release *relea
                              uint32_t type, bool interruptible)
 {
        struct qxl_command cmd;
+       struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head);
 
        cmd.type = type;
-       cmd.data = qxl_bo_physical_address(qdev, release->bos[0], release->release_offset);
+       cmd.data = qxl_bo_physical_address(qdev, to_qxl_bo(entry->tv.bo), release->release_offset);
 
        return qxl_ring_push(qdev->command_ring, &cmd, interruptible);
 }
@@ -191,9 +192,10 @@ qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *releas
                             uint32_t type, bool interruptible)
 {
        struct qxl_command cmd;
+       struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head);
 
        cmd.type = type;
-       cmd.data = qxl_bo_physical_address(qdev, release->bos[0], release->release_offset);
+       cmd.data = qxl_bo_physical_address(qdev, to_qxl_bo(entry->tv.bo), release->release_offset);
 
        return qxl_ring_push(qdev->cursor_ring, &cmd, interruptible);
 }
@@ -214,7 +216,6 @@ int qxl_garbage_collect(struct qxl_device *qdev)
        struct qxl_release *release;
        uint64_t id, next_id;
        int i = 0;
-       int ret;
        union qxl_release_info *info;
 
        while (qxl_ring_pop(qdev->release_ring, &id)) {
@@ -224,17 +225,10 @@ int qxl_garbage_collect(struct qxl_device *qdev)
                        if (release == NULL)
                                break;
 
-                       ret = qxl_release_reserve(qdev, release, false);
-                       if (ret) {
-                               qxl_io_log(qdev, "failed to reserve release on garbage collect %lld\n", id);
-                               DRM_ERROR("failed to reserve release %lld\n", id);
-                       }
-
                        info = qxl_release_map(qdev, release);
                        next_id = info->next;
                        qxl_release_unmap(qdev, release, info);
 
-                       qxl_release_unreserve(qdev, release);
                        QXL_INFO(qdev, "popped %lld, next %lld\n", id,
                                next_id);
 
@@ -259,27 +253,29 @@ int qxl_garbage_collect(struct qxl_device *qdev)
        return i;
 }
 
-int qxl_alloc_bo_reserved(struct qxl_device *qdev, unsigned long size,
+int qxl_alloc_bo_reserved(struct qxl_device *qdev,
+                         struct qxl_release *release,
+                         unsigned long size,
                          struct qxl_bo **_bo)
 {
        struct qxl_bo *bo;
        int ret;
 
        ret = qxl_bo_create(qdev, size, false /* not kernel - device */,
-                           QXL_GEM_DOMAIN_VRAM, NULL, &bo);
+                           false, QXL_GEM_DOMAIN_VRAM, NULL, &bo);
        if (ret) {
                DRM_ERROR("failed to allocate VRAM BO\n");
                return ret;
        }
-       ret = qxl_bo_reserve(bo, false);
-       if (unlikely(ret != 0))
+       ret = qxl_release_list_add(release, bo);
+       if (ret)
                goto out_unref;
 
        *_bo = bo;
        return 0;
 out_unref:
        qxl_bo_unref(&bo);
-       return 0;
+       return ret;
 }
 
 static int wait_for_io_cmd_user(struct qxl_device *qdev, uint8_t val, long port, bool intr)
@@ -503,6 +499,10 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
        if (ret)
                return ret;
 
+       ret = qxl_release_reserve_list(release, true);
+       if (ret)
+               return ret;
+
        cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release);
        cmd->type = QXL_SURFACE_CMD_CREATE;
        cmd->u.surface_create.format = surf->surf.format;
@@ -524,14 +524,11 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev,
 
        surf->surf_create = release;
 
-       /* no need to add a release to the fence for this bo,
+       /* no need to add a release to the fence for this surface bo,
           since it is only released when we ask to destroy the surface
           and it would never signal otherwise */
-       qxl_fence_releaseable(qdev, release);
-
        qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
-
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
 
        surf->hw_surf_alloc = true;
        spin_lock(&qdev->surf_id_idr_lock);
@@ -573,12 +570,9 @@ int qxl_hw_surface_dealloc(struct qxl_device *qdev,
        cmd->surface_id = id;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_fence_releaseable(qdev, release);
-
        qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
 
-       qxl_release_unreserve(qdev, release);
-
+       qxl_release_fence_buffer_objects(release);
 
        return 0;
 }
index f76f5dd7bfc43281b8c5fed9d06ffd6f0876eb92..835caba026d399d4e3750fbc3b47d44c7c6b7df5 100644 (file)
@@ -179,7 +179,7 @@ static void qxl_crtc_destroy(struct drm_crtc *crtc)
        kfree(qxl_crtc);
 }
 
-static void
+static int
 qxl_hide_cursor(struct qxl_device *qdev)
 {
        struct qxl_release *release;
@@ -188,14 +188,22 @@ qxl_hide_cursor(struct qxl_device *qdev)
 
        ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
                                         &release, NULL);
+       if (ret)
+               return ret;
+
+       ret = qxl_release_reserve_list(release, true);
+       if (ret) {
+               qxl_release_free(qdev, release);
+               return ret;
+       }
 
        cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
        cmd->type = QXL_CURSOR_HIDE;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_fence_releaseable(qdev, release);
        qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
+       return 0;
 }
 
 static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
@@ -216,10 +224,8 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
 
        int size = 64*64*4;
        int ret = 0;
-       if (!handle) {
-               qxl_hide_cursor(qdev);
-               return 0;
-       }
+       if (!handle)
+               return qxl_hide_cursor(qdev);
 
        obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
        if (!obj) {
@@ -234,8 +240,9 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
                goto out_unref;
 
        ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
+       qxl_bo_unreserve(user_bo);
        if (ret)
-               goto out_unreserve;
+               goto out_unref;
 
        ret = qxl_bo_kmap(user_bo, &user_ptr);
        if (ret)
@@ -246,14 +253,20 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
                                         &release, NULL);
        if (ret)
                goto out_kunmap;
-       ret = qxl_alloc_bo_reserved(qdev, sizeof(struct qxl_cursor) + size,
-                                   &cursor_bo);
+
+       ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size,
+                          &cursor_bo);
        if (ret)
                goto out_free_release;
-       ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
+
+       ret = qxl_release_reserve_list(release, false);
        if (ret)
                goto out_free_bo;
 
+       ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
+       if (ret)
+               goto out_backoff;
+
        cursor->header.unique = 0;
        cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
        cursor->header.width = 64;
@@ -269,11 +282,7 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
 
        qxl_bo_kunmap(cursor_bo);
 
-       /* finish with the userspace bo */
        qxl_bo_kunmap(user_bo);
-       qxl_bo_unpin(user_bo);
-       qxl_bo_unreserve(user_bo);
-       drm_gem_object_unreference_unlocked(obj);
 
        cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release);
        cmd->type = QXL_CURSOR_SET;
@@ -281,30 +290,35 @@ static int qxl_crtc_cursor_set2(struct drm_crtc *crtc,
        cmd->u.set.position.y = qcrtc->cur_y;
 
        cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0);
-       qxl_release_add_res(qdev, release, cursor_bo);
 
        cmd->u.set.visible = 1;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_fence_releaseable(qdev, release);
        qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
+
+       /* finish with the userspace bo */
+       ret = qxl_bo_reserve(user_bo, false);
+       if (!ret) {
+               qxl_bo_unpin(user_bo);
+               qxl_bo_unreserve(user_bo);
+       }
+       drm_gem_object_unreference_unlocked(obj);
 
-       qxl_bo_unreserve(cursor_bo);
        qxl_bo_unref(&cursor_bo);
 
        return ret;
+
+out_backoff:
+       qxl_release_backoff_reserve_list(release);
 out_free_bo:
        qxl_bo_unref(&cursor_bo);
 out_free_release:
-       qxl_release_unreserve(qdev, release);
        qxl_release_free(qdev, release);
 out_kunmap:
        qxl_bo_kunmap(user_bo);
 out_unpin:
        qxl_bo_unpin(user_bo);
-out_unreserve:
-       qxl_bo_unreserve(user_bo);
 out_unref:
        drm_gem_object_unreference_unlocked(obj);
        return ret;
@@ -322,6 +336,14 @@ static int qxl_crtc_cursor_move(struct drm_crtc *crtc,
 
        ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD,
                                   &release, NULL);
+       if (ret)
+               return ret;
+
+       ret = qxl_release_reserve_list(release, true);
+       if (ret) {
+               qxl_release_free(qdev, release);
+               return ret;
+       }
 
        qcrtc->cur_x = x;
        qcrtc->cur_y = y;
@@ -332,9 +354,9 @@ static int qxl_crtc_cursor_move(struct drm_crtc *crtc,
        cmd->u.position.y = qcrtc->cur_y;
        qxl_release_unmap(qdev, release, &cmd->release_info);
 
-       qxl_fence_releaseable(qdev, release);
        qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
+
        return 0;
 }
 
index 3c8c3dbf93782522eac671a3d6c8cf5f1af3e4bc..56e1d633875e2772b6a3f767e3af44e013f3519d 100644 (file)
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
+static int alloc_clips(struct qxl_device *qdev,
+                      struct qxl_release *release,
+                      unsigned num_clips,
+                      struct qxl_bo **clips_bo)
+{
+       int size = sizeof(struct qxl_clip_rects) + sizeof(struct qxl_rect) * num_clips;
+
+       return qxl_alloc_bo_reserved(qdev, release, size, clips_bo);
+}
+
 /* returns a pointer to the already allocated qxl_rect array inside
  * the qxl_clip_rects. This is *not* the same as the memory allocated
  * on the device, it is offset to qxl_clip_rects.chunk.data */
 static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev,
                                              struct qxl_drawable *drawable,
                                              unsigned num_clips,
-                                             struct qxl_bo **clips_bo,
-                                             struct qxl_release *release)
+                                             struct qxl_bo *clips_bo)
 {
        struct qxl_clip_rects *dev_clips;
        int ret;
-       int size = sizeof(*dev_clips) + sizeof(struct qxl_rect) * num_clips;
-       ret = qxl_alloc_bo_reserved(qdev, size, clips_bo);
-       if (ret)
-               return NULL;
 
-       ret = qxl_bo_kmap(*clips_bo, (void **)&dev_clips);
+       ret = qxl_bo_kmap(clips_bo, (void **)&dev_clips);
        if (ret) {
-               qxl_bo_unref(clips_bo);
                return NULL;
        }
        dev_clips->num_rects = num_clips;
@@ -51,21 +55,35 @@ static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev,
        return (struct qxl_rect *)dev_clips->chunk.data;
 }
 
+static int
+alloc_drawable(struct qxl_device *qdev, struct qxl_release **release)
+{
+       int ret;
+       ret = qxl_alloc_release_reserved(qdev, sizeof(struct qxl_drawable),
+                                        QXL_RELEASE_DRAWABLE, release,
+                                        NULL);
+       return ret;
+}
+
+static void
+free_drawable(struct qxl_device *qdev, struct qxl_release *release)
+{
+       qxl_release_free(qdev, release);
+}
+
+/* release needs to be reserved at this point */
 static int
 make_drawable(struct qxl_device *qdev, int surface, uint8_t type,
              const struct qxl_rect *rect,
-             struct qxl_release **release)
+             struct qxl_release *release)
 {
        struct qxl_drawable *drawable;
-       int i, ret;
+       int i;
 
-       ret = qxl_alloc_release_reserved(qdev, sizeof(*drawable),
-                                        QXL_RELEASE_DRAWABLE, release,
-                                        NULL);
-       if (ret)
-               return ret;
+       drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
+       if (!drawable)
+               return -ENOMEM;
 
-       drawable = (struct qxl_drawable *)qxl_release_map(qdev, *release);
        drawable->type = type;
 
        drawable->surface_id = surface;         /* Only primary for now */
@@ -91,14 +109,23 @@ make_drawable(struct qxl_device *qdev, int surface, uint8_t type,
                drawable->bbox = *rect;
 
        drawable->mm_time = qdev->rom->mm_clock;
-       qxl_release_unmap(qdev, *release, &drawable->release_info);
+       qxl_release_unmap(qdev, release, &drawable->release_info);
        return 0;
 }
 
-static int qxl_palette_create_1bit(struct qxl_bo **palette_bo,
+static int alloc_palette_object(struct qxl_device *qdev,
+                               struct qxl_release *release,
+                               struct qxl_bo **palette_bo)
+{
+       return qxl_alloc_bo_reserved(qdev, release,
+                                    sizeof(struct qxl_palette) + sizeof(uint32_t) * 2,
+                                    palette_bo);
+}
+
+static int qxl_palette_create_1bit(struct qxl_bo *palette_bo,
+                                  struct qxl_release *release,
                                   const struct qxl_fb_image *qxl_fb_image)
 {
-       struct qxl_device *qdev = qxl_fb_image->qdev;
        const struct fb_image *fb_image = &qxl_fb_image->fb_image;
        uint32_t visual = qxl_fb_image->visual;
        const uint32_t *pseudo_palette = qxl_fb_image->pseudo_palette;
@@ -108,12 +135,7 @@ static int qxl_palette_create_1bit(struct qxl_bo **palette_bo,
        static uint64_t unique; /* we make no attempt to actually set this
                                 * correctly globaly, since that would require
                                 * tracking all of our palettes. */
-
-       ret = qxl_alloc_bo_reserved(qdev,
-                                   sizeof(struct qxl_palette) + sizeof(uint32_t) * 2,
-                                   palette_bo);
-
-       ret = qxl_bo_kmap(*palette_bo, (void **)&pal);
+       ret = qxl_bo_kmap(palette_bo, (void **)&pal);
        pal->num_ents = 2;
        pal->unique = unique++;
        if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) {
@@ -126,7 +148,7 @@ static int qxl_palette_create_1bit(struct qxl_bo **palette_bo,
        }
        pal->ents[0] = bgcolor;
        pal->ents[1] = fgcolor;
-       qxl_bo_kunmap(*palette_bo);
+       qxl_bo_kunmap(palette_bo);
        return 0;
 }
 
@@ -144,44 +166,63 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
        const char *src = fb_image->data;
        int depth = fb_image->depth;
        struct qxl_release *release;
-       struct qxl_bo *image_bo;
        struct qxl_image *image;
        int ret;
-
+       struct qxl_drm_image *dimage;
+       struct qxl_bo *palette_bo = NULL;
        if (stride == 0)
                stride = depth * width / 8;
 
+       ret = alloc_drawable(qdev, &release);
+       if (ret)
+               return;
+
+       ret = qxl_image_alloc_objects(qdev, release,
+                                     &dimage,
+                                     height, stride);
+       if (ret)
+               goto out_free_drawable;
+
+       if (depth == 1) {
+               ret = alloc_palette_object(qdev, release, &palette_bo);
+               if (ret)
+                       goto out_free_image;
+       }
+
+       /* do a reservation run over all the objects we just allocated */
+       ret = qxl_release_reserve_list(release, true);
+       if (ret)
+               goto out_free_palette;
+
        rect.left = x;
        rect.right = x + width;
        rect.top = y;
        rect.bottom = y + height;
 
-       ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &rect, &release);
-       if (ret)
-               return;
+       ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &rect, release);
+       if (ret) {
+               qxl_release_backoff_reserve_list(release);
+               goto out_free_palette;
+       }
 
-       ret = qxl_image_create(qdev, release, &image_bo,
-                              (const uint8_t *)src, 0, 0,
-                              width, height, depth, stride);
+       ret = qxl_image_init(qdev, release, dimage,
+                            (const uint8_t *)src, 0, 0,
+                            width, height, depth, stride);
        if (ret) {
-               qxl_release_unreserve(qdev, release);
+               qxl_release_backoff_reserve_list(release);
                qxl_release_free(qdev, release);
                return;
        }
 
        if (depth == 1) {
-               struct qxl_bo *palette_bo;
                void *ptr;
-               ret = qxl_palette_create_1bit(&palette_bo, qxl_fb_image);
-               qxl_release_add_res(qdev, release, palette_bo);
+               ret = qxl_palette_create_1bit(palette_bo, release, qxl_fb_image);
 
-               ptr = qxl_bo_kmap_atomic_page(qdev, image_bo, 0);
+               ptr = qxl_bo_kmap_atomic_page(qdev, dimage->bo, 0);
                image = ptr;
                image->u.bitmap.palette =
                        qxl_bo_physical_address(qdev, palette_bo, 0);
-               qxl_bo_kunmap_atomic_page(qdev, image_bo, ptr);
-               qxl_bo_unreserve(palette_bo);
-               qxl_bo_unref(&palette_bo);
+               qxl_bo_kunmap_atomic_page(qdev, dimage->bo, ptr);
        }
 
        drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
@@ -199,16 +240,20 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
        drawable->u.copy.mask.bitmap = 0;
 
        drawable->u.copy.src_bitmap =
-               qxl_bo_physical_address(qdev, image_bo, 0);
+               qxl_bo_physical_address(qdev, dimage->bo, 0);
        qxl_release_unmap(qdev, release, &drawable->release_info);
 
-       qxl_release_add_res(qdev, release, image_bo);
-       qxl_bo_unreserve(image_bo);
-       qxl_bo_unref(&image_bo);
-
-       qxl_fence_releaseable(qdev, release);
        qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
+
+out_free_palette:
+       if (palette_bo)
+               qxl_bo_unref(&palette_bo);
+out_free_image:
+       qxl_image_free_objects(qdev, dimage);
+out_free_drawable:
+       if (ret)
+               free_drawable(qdev, release);
 }
 
 /* push a draw command using the given clipping rectangles as
@@ -243,10 +288,14 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
        int depth = qxl_fb->base.bits_per_pixel;
        uint8_t *surface_base;
        struct qxl_release *release;
-       struct qxl_bo *image_bo;
        struct qxl_bo *clips_bo;
+       struct qxl_drm_image *dimage;
        int ret;
 
+       ret = alloc_drawable(qdev, &release);
+       if (ret)
+               return;
+
        left = clips->x1;
        right = clips->x2;
        top = clips->y1;
@@ -263,36 +312,52 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
 
        width = right - left;
        height = bottom - top;
+
+       ret = alloc_clips(qdev, release, num_clips, &clips_bo);
+       if (ret)
+               goto out_free_drawable;
+
+       ret = qxl_image_alloc_objects(qdev, release,
+                                     &dimage,
+                                     height, stride);
+       if (ret)
+               goto out_free_clips;
+
+       /* do a reservation run over all the objects we just allocated */
+       ret = qxl_release_reserve_list(release, true);
+       if (ret)
+               goto out_free_image;
+
        drawable_rect.left = left;
        drawable_rect.right = right;
        drawable_rect.top = top;
        drawable_rect.bottom = bottom;
+
        ret = make_drawable(qdev, 0, QXL_DRAW_COPY, &drawable_rect,
-                           &release);
+                           release);
        if (ret)
-               return;
+               goto out_release_backoff;
 
        ret = qxl_bo_kmap(bo, (void **)&surface_base);
        if (ret)
-               goto out_unref;
+               goto out_release_backoff;
 
-       ret = qxl_image_create(qdev, release, &image_bo, surface_base,
-                              left, top, width, height, depth, stride);
+
+       ret = qxl_image_init(qdev, release, dimage, surface_base,
+                            left, top, width, height, depth, stride);
        qxl_bo_kunmap(bo);
        if (ret)
-               goto out_unref;
+               goto out_release_backoff;
+
+       rects = drawable_set_clipping(qdev, drawable, num_clips, clips_bo);
+       if (!rects)
+               goto out_release_backoff;
 
-       rects = drawable_set_clipping(qdev, drawable, num_clips, &clips_bo, release);
-       if (!rects) {
-               qxl_bo_unref(&image_bo);
-               goto out_unref;
-       }
        drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
 
        drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
        drawable->clip.data = qxl_bo_physical_address(qdev,
                                                      clips_bo, 0);
-       qxl_release_add_res(qdev, release, clips_bo);
 
        drawable->u.copy.src_area.top = 0;
        drawable->u.copy.src_area.bottom = height;
@@ -306,11 +371,9 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
        drawable->u.copy.mask.pos.y = 0;
        drawable->u.copy.mask.bitmap = 0;
 
-       drawable->u.copy.src_bitmap = qxl_bo_physical_address(qdev, image_bo, 0);
+       drawable->u.copy.src_bitmap = qxl_bo_physical_address(qdev, dimage->bo, 0);
        qxl_release_unmap(qdev, release, &drawable->release_info);
-       qxl_release_add_res(qdev, release, image_bo);
-       qxl_bo_unreserve(image_bo);
-       qxl_bo_unref(&image_bo);
+
        clips_ptr = clips;
        for (i = 0; i < num_clips; i++, clips_ptr += inc) {
                rects[i].left   = clips_ptr->x1;
@@ -319,17 +382,22 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
                rects[i].bottom = clips_ptr->y2;
        }
        qxl_bo_kunmap(clips_bo);
-       qxl_bo_unreserve(clips_bo);
-       qxl_bo_unref(&clips_bo);
 
-       qxl_fence_releaseable(qdev, release);
        qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-       qxl_release_unreserve(qdev, release);
-       return;
+       qxl_release_fence_buffer_objects(release);
+
+out_release_backoff:
+       if (ret)
+               qxl_release_backoff_reserve_list(release);
+out_free_image:
+       qxl_image_free_objects(qdev, dimage);
+out_free_clips:
+       qxl_bo_unref(&clips_bo);
+out_free_drawable:
+       /* only free drawable on error */
+       if (ret)
+               free_drawable(qdev, release);
 
-out_unref:
-       qxl_release_unreserve(qdev, release);
-       qxl_release_free(qdev, release);
 }
 
 void qxl_draw_copyarea(struct qxl_device *qdev,
@@ -342,22 +410,36 @@ void qxl_draw_copyarea(struct qxl_device *qdev,
        struct qxl_release *release;
        int ret;
 
+       ret = alloc_drawable(qdev, &release);
+       if (ret)
+               return;
+
+       /* do a reservation run over all the objects we just allocated */
+       ret = qxl_release_reserve_list(release, true);
+       if (ret)
+               goto out_free_release;
+
        rect.left = dx;
        rect.top = dy;
        rect.right = dx + width;
        rect.bottom = dy + height;
-       ret = make_drawable(qdev, 0, QXL_COPY_BITS, &rect, &release);
-       if (ret)
-               return;
+       ret = make_drawable(qdev, 0, QXL_COPY_BITS, &rect, release);
+       if (ret) {
+               qxl_release_backoff_reserve_list(release);
+               goto out_free_release;
+       }
 
        drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
        drawable->u.copy_bits.src_pos.x = sx;
        drawable->u.copy_bits.src_pos.y = sy;
-
        qxl_release_unmap(qdev, release, &drawable->release_info);
-       qxl_fence_releaseable(qdev, release);
+
        qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
+
+out_free_release:
+       if (ret)
+               free_drawable(qdev, release);
 }
 
 void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec)
@@ -370,10 +452,21 @@ void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec)
        struct qxl_release *release;
        int ret;
 
-       ret = make_drawable(qdev, 0, QXL_DRAW_FILL, &rect, &release);
+       ret = alloc_drawable(qdev, &release);
        if (ret)
                return;
 
+       /* do a reservation run over all the objects we just allocated */
+       ret = qxl_release_reserve_list(release, true);
+       if (ret)
+               goto out_free_release;
+
+       ret = make_drawable(qdev, 0, QXL_DRAW_FILL, &rect, release);
+       if (ret) {
+               qxl_release_backoff_reserve_list(release);
+               goto out_free_release;
+       }
+
        drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
        drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID;
        drawable->u.fill.brush.u.color = color;
@@ -384,7 +477,11 @@ void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec)
        drawable->u.fill.mask.bitmap = 0;
 
        qxl_release_unmap(qdev, release, &drawable->release_info);
-       qxl_fence_releaseable(qdev, release);
+
        qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
-       qxl_release_unreserve(qdev, release);
+       qxl_release_fence_buffer_objects(release);
+
+out_free_release:
+       if (ret)
+               free_drawable(qdev, release);
 }
index afd09d48d72ccbe2262229cb1849af3c811be369..4708621fe720b8f1624f44b1f4233a0bbe2317e4 100644 (file)
@@ -42,6 +42,9 @@
 #include <ttm/ttm_placement.h>
 #include <ttm/ttm_module.h>
 
+/* just for ttm_validate_buffer */
+#include <ttm/ttm_execbuf_util.h>
+
 #include <drm/qxl_drm.h>
 #include "qxl_dev.h"
 
@@ -118,9 +121,9 @@ struct qxl_bo {
        uint32_t surface_id;
        struct qxl_fence fence; /* per bo fence  - list of releases */
        struct qxl_release *surf_create;
-       atomic_t reserve_count;
 };
 #define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, gem_base)
+#define to_qxl_bo(tobj) container_of((tobj), struct qxl_bo, tbo)
 
 struct qxl_gem {
        struct mutex            mutex;
@@ -128,12 +131,7 @@ struct qxl_gem {
 };
 
 struct qxl_bo_list {
-       struct list_head lhead;
-       struct qxl_bo *bo;
-};
-
-struct qxl_reloc_list {
-       struct list_head bos;
+       struct ttm_validate_buffer tv;
 };
 
 struct qxl_crtc {
@@ -195,10 +193,20 @@ enum {
 struct qxl_release {
        int id;
        int type;
-       int bo_count;
        uint32_t release_offset;
        uint32_t surface_release_id;
-       struct qxl_bo *bos[QXL_MAX_RES];
+       struct ww_acquire_ctx ticket;
+       struct list_head bos;
+};
+
+struct qxl_drm_chunk {
+       struct list_head head;
+       struct qxl_bo *bo;
+};
+
+struct qxl_drm_image {
+       struct qxl_bo *bo;
+       struct list_head chunk_list;
 };
 
 struct qxl_fb_image {
@@ -314,6 +322,7 @@ struct qxl_device {
        struct workqueue_struct *gc_queue;
        struct work_struct gc_work;
 
+       struct work_struct fb_work;
 };
 
 /* forward declaration for QXL_INFO_IO */
@@ -430,12 +439,19 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma);
 
 /* qxl image */
 
-int qxl_image_create(struct qxl_device *qdev,
-                    struct qxl_release *release,
-                    struct qxl_bo **image_bo,
-                    const uint8_t *data,
-                    int x, int y, int width, int height,
-                    int depth, int stride);
+int qxl_image_init(struct qxl_device *qdev,
+                  struct qxl_release *release,
+                  struct qxl_drm_image *dimage,
+                  const uint8_t *data,
+                  int x, int y, int width, int height,
+                  int depth, int stride);
+int
+qxl_image_alloc_objects(struct qxl_device *qdev,
+                       struct qxl_release *release,
+                       struct qxl_drm_image **image_ptr,
+                       int height, int stride);
+void qxl_image_free_objects(struct qxl_device *qdev, struct qxl_drm_image *dimage);
+
 void qxl_update_screen(struct qxl_device *qxl);
 
 /* qxl io operations (qxl_cmd.c) */
@@ -456,20 +472,15 @@ int qxl_ring_push(struct qxl_ring *ring, const void *new_elt, bool interruptible
 void qxl_io_flush_release(struct qxl_device *qdev);
 void qxl_io_flush_surfaces(struct qxl_device *qdev);
 
-int qxl_release_reserve(struct qxl_device *qdev,
-                       struct qxl_release *release, bool no_wait);
-void qxl_release_unreserve(struct qxl_device *qdev,
-                          struct qxl_release *release);
 union qxl_release_info *qxl_release_map(struct qxl_device *qdev,
                                        struct qxl_release *release);
 void qxl_release_unmap(struct qxl_device *qdev,
                       struct qxl_release *release,
                       union qxl_release_info *info);
-/*
- * qxl_bo_add_resource.
- *
- */
-void qxl_bo_add_resource(struct qxl_bo *main_bo, struct qxl_bo *resource);
+int qxl_release_list_add(struct qxl_release *release, struct qxl_bo *bo);
+int qxl_release_reserve_list(struct qxl_release *release, bool no_intr);
+void qxl_release_backoff_reserve_list(struct qxl_release *release);
+void qxl_release_fence_buffer_objects(struct qxl_release *release);
 
 int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
                                       enum qxl_surface_cmd_type surface_cmd_type,
@@ -478,15 +489,16 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
 int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
                               int type, struct qxl_release **release,
                               struct qxl_bo **rbo);
-int qxl_fence_releaseable(struct qxl_device *qdev,
-                         struct qxl_release *release);
+
 int
 qxl_push_command_ring_release(struct qxl_device *qdev, struct qxl_release *release,
                              uint32_t type, bool interruptible);
 int
 qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *release,
                             uint32_t type, bool interruptible);
-int qxl_alloc_bo_reserved(struct qxl_device *qdev, unsigned long size,
+int qxl_alloc_bo_reserved(struct qxl_device *qdev,
+                         struct qxl_release *release,
+                         unsigned long size,
                          struct qxl_bo **_bo);
 /* qxl drawing commands */
 
@@ -507,15 +519,9 @@ void qxl_draw_copyarea(struct qxl_device *qdev,
                       u32 sx, u32 sy,
                       u32 dx, u32 dy);
 
-uint64_t
-qxl_release_alloc(struct qxl_device *qdev, int type,
-                 struct qxl_release **ret);
-
 void qxl_release_free(struct qxl_device *qdev,
                      struct qxl_release *release);
-void qxl_release_add_res(struct qxl_device *qdev,
-                        struct qxl_release *release,
-                        struct qxl_bo *bo);
+
 /* used by qxl_debugfs_release */
 struct qxl_release *qxl_release_from_id_locked(struct qxl_device *qdev,
                                                   uint64_t id);
@@ -558,7 +564,7 @@ void qxl_surface_evict(struct qxl_device *qdev, struct qxl_bo *surf, bool freein
 int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf);
 
 /* qxl_fence.c */
-int qxl_fence_add_release(struct qxl_fence *qfence, uint32_t rel_id);
+void qxl_fence_add_release_locked(struct qxl_fence *qfence, uint32_t rel_id);
 int qxl_fence_remove_release(struct qxl_fence *qfence, uint32_t rel_id);
 int qxl_fence_init(struct qxl_device *qdev, struct qxl_fence *qfence);
 void qxl_fence_fini(struct qxl_fence *qfence);
index 76f39d88d684fbd979bc50ebf2047eceaa9ad632..88722f233430a3d0f7eb4e8b35ad929b709c5b35 100644 (file)
 
 #define QXL_DIRTY_DELAY (HZ / 30)
 
+#define QXL_FB_OP_FILLRECT 1
+#define QXL_FB_OP_COPYAREA 2
+#define QXL_FB_OP_IMAGEBLIT 3
+
+struct qxl_fb_op {
+       struct list_head head;
+       int op_type;
+       union {
+               struct fb_fillrect fr;
+               struct fb_copyarea ca;
+               struct fb_image ib;
+       } op;
+       void *img_data;
+};
+
 struct qxl_fbdev {
        struct drm_fb_helper helper;
        struct qxl_framebuffer  qfb;
        struct list_head        fbdev_list;
        struct qxl_device       *qdev;
 
+       spinlock_t delayed_ops_lock;
+       struct list_head delayed_ops;
        void *shadow;
        int size;
 
@@ -164,8 +181,69 @@ static struct fb_deferred_io qxl_defio = {
        .deferred_io    = qxl_deferred_io,
 };
 
-static void qxl_fb_fillrect(struct fb_info *info,
-                           const struct fb_fillrect *fb_rect)
+static void qxl_fb_delayed_fillrect(struct qxl_fbdev *qfbdev,
+                                   const struct fb_fillrect *fb_rect)
+{
+       struct qxl_fb_op *op;
+       unsigned long flags;
+
+       op = kmalloc(sizeof(struct qxl_fb_op), GFP_ATOMIC | __GFP_NOWARN);
+       if (!op)
+               return;
+
+       op->op.fr = *fb_rect;
+       op->img_data = NULL;
+       op->op_type = QXL_FB_OP_FILLRECT;
+
+       spin_lock_irqsave(&qfbdev->delayed_ops_lock, flags);
+       list_add_tail(&op->head, &qfbdev->delayed_ops);
+       spin_unlock_irqrestore(&qfbdev->delayed_ops_lock, flags);
+}
+
+static void qxl_fb_delayed_copyarea(struct qxl_fbdev *qfbdev,
+                                   const struct fb_copyarea *fb_copy)
+{
+       struct qxl_fb_op *op;
+       unsigned long flags;
+
+       op = kmalloc(sizeof(struct qxl_fb_op), GFP_ATOMIC | __GFP_NOWARN);
+       if (!op)
+               return;
+
+       op->op.ca = *fb_copy;
+       op->img_data = NULL;
+       op->op_type = QXL_FB_OP_COPYAREA;
+
+       spin_lock_irqsave(&qfbdev->delayed_ops_lock, flags);
+       list_add_tail(&op->head, &qfbdev->delayed_ops);
+       spin_unlock_irqrestore(&qfbdev->delayed_ops_lock, flags);
+}
+
+static void qxl_fb_delayed_imageblit(struct qxl_fbdev *qfbdev,
+                                    const struct fb_image *fb_image)
+{
+       struct qxl_fb_op *op;
+       unsigned long flags;
+       uint32_t size = fb_image->width * fb_image->height * (fb_image->depth >= 8 ? fb_image->depth / 8 : 1);
+
+       op = kmalloc(sizeof(struct qxl_fb_op) + size, GFP_ATOMIC | __GFP_NOWARN);
+       if (!op)
+               return;
+
+       op->op.ib = *fb_image;
+       op->img_data = (void *)(op + 1);
+       op->op_type = QXL_FB_OP_IMAGEBLIT;
+
+       memcpy(op->img_data, fb_image->data, size);
+
+       op->op.ib.data = op->img_data;
+       spin_lock_irqsave(&qfbdev->delayed_ops_lock, flags);
+       list_add_tail(&op->head, &qfbdev->delayed_ops);
+       spin_unlock_irqrestore(&qfbdev->delayed_ops_lock, flags);
+}
+
+static void qxl_fb_fillrect_internal(struct fb_info *info,
+                                    const struct fb_fillrect *fb_rect)
 {
        struct qxl_fbdev *qfbdev = info->par;
        struct qxl_device *qdev = qfbdev->qdev;
@@ -203,17 +281,28 @@ static void qxl_fb_fillrect(struct fb_info *info,
        qxl_draw_fill_rec.rect = rect;
        qxl_draw_fill_rec.color = color;
        qxl_draw_fill_rec.rop = rop;
+
+       qxl_draw_fill(&qxl_draw_fill_rec);
+}
+
+static void qxl_fb_fillrect(struct fb_info *info,
+                           const struct fb_fillrect *fb_rect)
+{
+       struct qxl_fbdev *qfbdev = info->par;
+       struct qxl_device *qdev = qfbdev->qdev;
+
        if (!drm_can_sleep()) {
-               qxl_io_log(qdev,
-                       "%s: TODO use RCU, mysterious locks with spin_lock\n",
-                       __func__);
+               qxl_fb_delayed_fillrect(qfbdev, fb_rect);
+               schedule_work(&qdev->fb_work);
                return;
        }
-       qxl_draw_fill(&qxl_draw_fill_rec);
+       /* make sure any previous work is done */
+       flush_work(&qdev->fb_work);
+       qxl_fb_fillrect_internal(info, fb_rect);
 }
 
-static void qxl_fb_copyarea(struct fb_info *info,
-                           const struct fb_copyarea *region)
+static void qxl_fb_copyarea_internal(struct fb_info *info,
+                                    const struct fb_copyarea *region)
 {
        struct qxl_fbdev *qfbdev = info->par;
 
@@ -223,37 +312,89 @@ static void qxl_fb_copyarea(struct fb_info *info,
                          region->dx, region->dy);
 }
 
+static void qxl_fb_copyarea(struct fb_info *info,
+                           const struct fb_copyarea *region)
+{
+       struct qxl_fbdev *qfbdev = info->par;
+       struct qxl_device *qdev = qfbdev->qdev;
+
+       if (!drm_can_sleep()) {
+               qxl_fb_delayed_copyarea(qfbdev, region);
+               schedule_work(&qdev->fb_work);
+               return;
+       }
+       /* make sure any previous work is done */
+       flush_work(&qdev->fb_work);
+       qxl_fb_copyarea_internal(info, region);
+}
+
 static void qxl_fb_imageblit_safe(struct qxl_fb_image *qxl_fb_image)
 {
        qxl_draw_opaque_fb(qxl_fb_image, 0);
 }
 
+static void qxl_fb_imageblit_internal(struct fb_info *info,
+                                     const struct fb_image *image)
+{
+       struct qxl_fbdev *qfbdev = info->par;
+       struct qxl_fb_image qxl_fb_image;
+
+       /* ensure proper order  rendering operations - TODO: must do this
+        * for everything. */
+       qxl_fb_image_init(&qxl_fb_image, qfbdev->qdev, info, image);
+       qxl_fb_imageblit_safe(&qxl_fb_image);
+}
+
 static void qxl_fb_imageblit(struct fb_info *info,
                             const struct fb_image *image)
 {
        struct qxl_fbdev *qfbdev = info->par;
        struct qxl_device *qdev = qfbdev->qdev;
-       struct qxl_fb_image qxl_fb_image;
 
        if (!drm_can_sleep()) {
-               /* we cannot do any ttm_bo allocation since that will fail on
-                * ioremap_wc..__get_vm_area_node, so queue the work item
-                * instead This can happen from printk inside an interrupt
-                * context, i.e.: smp_apic_timer_interrupt..check_cpu_stall */
-               qxl_io_log(qdev,
-                       "%s: TODO use RCU, mysterious locks with spin_lock\n",
-                          __func__);
+               qxl_fb_delayed_imageblit(qfbdev, image);
+               schedule_work(&qdev->fb_work);
                return;
        }
+       /* make sure any previous work is done */
+       flush_work(&qdev->fb_work);
+       qxl_fb_imageblit_internal(info, image);
+}
 
-       /* ensure proper order of rendering operations - TODO: must do this
-        * for everything. */
-       qxl_fb_image_init(&qxl_fb_image, qfbdev->qdev, info, image);
-       qxl_fb_imageblit_safe(&qxl_fb_image);
+static void qxl_fb_work(struct work_struct *work)
+{
+       struct qxl_device *qdev = container_of(work, struct qxl_device, fb_work);
+       unsigned long flags;
+       struct qxl_fb_op *entry, *tmp;
+       struct qxl_fbdev *qfbdev = qdev->mode_info.qfbdev;
+
+       /* since the irq context just adds entries to the end of the
+          list dropping the lock should be fine, as entry isn't modified
+          in the operation code */
+       spin_lock_irqsave(&qfbdev->delayed_ops_lock, flags);
+       list_for_each_entry_safe(entry, tmp, &qfbdev->delayed_ops, head) {
+               spin_unlock_irqrestore(&qfbdev->delayed_ops_lock, flags);
+               switch (entry->op_type) {
+               case QXL_FB_OP_FILLRECT:
+                       qxl_fb_fillrect_internal(qfbdev->helper.fbdev, &entry->op.fr);
+                       break;
+               case QXL_FB_OP_COPYAREA:
+                       qxl_fb_copyarea_internal(qfbdev->helper.fbdev, &entry->op.ca);
+                       break;
+               case QXL_FB_OP_IMAGEBLIT:
+                       qxl_fb_imageblit_internal(qfbdev->helper.fbdev, &entry->op.ib);
+                       break;
+               }
+               spin_lock_irqsave(&qfbdev->delayed_ops_lock, flags);
+               list_del(&entry->head);
+               kfree(entry);
+       }
+       spin_unlock_irqrestore(&qfbdev->delayed_ops_lock, flags);
 }
 
 int qxl_fb_init(struct qxl_device *qdev)
 {
+       INIT_WORK(&qdev->fb_work, qxl_fb_work);
        return 0;
 }
 
@@ -536,7 +677,8 @@ int qxl_fbdev_init(struct qxl_device *qdev)
        qfbdev->qdev = qdev;
        qdev->mode_info.qfbdev = qfbdev;
        qfbdev->helper.funcs = &qxl_fb_helper_funcs;
-
+       spin_lock_init(&qfbdev->delayed_ops_lock);
+       INIT_LIST_HEAD(&qfbdev->delayed_ops);
        ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper,
                                 qxl_num_crtc /* num_crtc - QXL supports just 1 */,
                                 QXLFB_CONN_LIMIT);
index 63c6715ad38565d5ad5c04243b00d4482c54b7b5..ae59e91cfb9ab1694aee3047e094166130e7b123 100644 (file)
 
    For some reason every so often qxl hw fails to release, things go wrong.
 */
-
-
-int qxl_fence_add_release(struct qxl_fence *qfence, uint32_t rel_id)
+/* must be called with the fence lock held */
+void qxl_fence_add_release_locked(struct qxl_fence *qfence, uint32_t rel_id)
 {
-       struct qxl_bo *bo = container_of(qfence, struct qxl_bo, fence);
-
-       spin_lock(&bo->tbo.bdev->fence_lock);
        radix_tree_insert(&qfence->tree, rel_id, qfence);
        qfence->num_active_releases++;
-       spin_unlock(&bo->tbo.bdev->fence_lock);
-       return 0;
 }
 
 int qxl_fence_remove_release(struct qxl_fence *qfence, uint32_t rel_id)
index a235693aabba331284fca3017c519002789c1ab9..25e1777fb0a28551ac1d43d8a7a5b183812f54a7 100644 (file)
@@ -55,7 +55,7 @@ int qxl_gem_object_create(struct qxl_device *qdev, int size,
        /* At least align on page size */
        if (alignment < PAGE_SIZE)
                alignment = PAGE_SIZE;
-       r = qxl_bo_create(qdev, size, kernel, initial_domain, surf, &qbo);
+       r = qxl_bo_create(qdev, size, kernel, false, initial_domain, surf, &qbo);
        if (r) {
                if (r != -ERESTARTSYS)
                        DRM_ERROR(
index cf856206996b86a6b2293723faafc1c14810a64d..7fbcc35e8ad35bfa8cce9f3323a4f4e5d574f21e 100644 (file)
 #include "qxl_object.h"
 
 static int
-qxl_image_create_helper(struct qxl_device *qdev,
+qxl_allocate_chunk(struct qxl_device *qdev,
+                  struct qxl_release *release,
+                  struct qxl_drm_image *image,
+                  unsigned int chunk_size)
+{
+       struct qxl_drm_chunk *chunk;
+       int ret;
+
+       chunk = kmalloc(sizeof(struct qxl_drm_chunk), GFP_KERNEL);
+       if (!chunk)
+               return -ENOMEM;
+
+       ret = qxl_alloc_bo_reserved(qdev, release, chunk_size, &chunk->bo);
+       if (ret) {
+               kfree(chunk);
+               return ret;
+       }
+
+       list_add_tail(&chunk->head, &image->chunk_list);
+       return 0;
+}
+
+int
+qxl_image_alloc_objects(struct qxl_device *qdev,
                        struct qxl_release *release,
-                       struct qxl_bo **image_bo,
-                       const uint8_t *data,
-                       int width, int height,
-                       int depth, unsigned int hash,
-                       int stride)
+                       struct qxl_drm_image **image_ptr,
+                       int height, int stride)
+{
+       struct qxl_drm_image *image;
+       int ret;
+
+       image = kmalloc(sizeof(struct qxl_drm_image), GFP_KERNEL);
+       if (!image)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&image->chunk_list);
+
+       ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_image), &image->bo);
+       if (ret) {
+               kfree(image);
+               return ret;
+       }
+
+       ret = qxl_allocate_chunk(qdev, release, image, sizeof(struct qxl_data_chunk) + stride * height);
+       if (ret) {
+               qxl_bo_unref(&image->bo);
+               kfree(image);
+               return ret;
+       }
+       *image_ptr = image;
+       return 0;
+}
+
+void qxl_image_free_objects(struct qxl_device *qdev, struct qxl_drm_image *dimage)
 {
+       struct qxl_drm_chunk *chunk, *tmp;
+
+       list_for_each_entry_safe(chunk, tmp, &dimage->chunk_list, head) {
+               qxl_bo_unref(&chunk->bo);
+               kfree(chunk);
+       }
+
+       qxl_bo_unref(&dimage->bo);
+       kfree(dimage);
+}
+
+static int
+qxl_image_init_helper(struct qxl_device *qdev,
+                     struct qxl_release *release,
+                     struct qxl_drm_image *dimage,
+                     const uint8_t *data,
+                     int width, int height,
+                     int depth, unsigned int hash,
+                     int stride)
+{
+       struct qxl_drm_chunk *drv_chunk;
        struct qxl_image *image;
        struct qxl_data_chunk *chunk;
        int i;
        int chunk_stride;
        int linesize = width * depth / 8;
-       struct qxl_bo *chunk_bo;
-       int ret;
+       struct qxl_bo *chunk_bo, *image_bo;
        void *ptr;
        /* Chunk */
        /* FIXME: Check integer overflow */
        /* TODO: variable number of chunks */
+
+       drv_chunk = list_first_entry(&dimage->chunk_list, struct qxl_drm_chunk, head);
+
+       chunk_bo = drv_chunk->bo;
        chunk_stride = stride; /* TODO: should use linesize, but it renders
                                  wrong (check the bitmaps are sent correctly
                                  first) */
-       ret = qxl_alloc_bo_reserved(qdev, sizeof(*chunk) + height * chunk_stride,
-                                   &chunk_bo);
-       
+
        ptr = qxl_bo_kmap_atomic_page(qdev, chunk_bo, 0);
        chunk = ptr;
        chunk->data_size = height * chunk_stride;
@@ -102,7 +171,6 @@ qxl_image_create_helper(struct qxl_device *qdev,
                                while (remain > 0) {
                                        page_base = out_offset & PAGE_MASK;
                                        page_offset = offset_in_page(out_offset);
-                                       
                                        size = min((int)(PAGE_SIZE - page_offset), remain);
 
                                        ptr = qxl_bo_kmap_atomic_page(qdev, chunk_bo, page_base);
@@ -116,14 +184,10 @@ qxl_image_create_helper(struct qxl_device *qdev,
                        }
                }
        }
-
-
        qxl_bo_kunmap(chunk_bo);
 
-       /* Image */
-       ret = qxl_alloc_bo_reserved(qdev, sizeof(*image), image_bo);
-
-       ptr = qxl_bo_kmap_atomic_page(qdev, *image_bo, 0);
+       image_bo = dimage->bo;
+       ptr = qxl_bo_kmap_atomic_page(qdev, image_bo, 0);
        image = ptr;
 
        image->descriptor.id = 0;
@@ -154,23 +218,20 @@ qxl_image_create_helper(struct qxl_device *qdev,
        image->u.bitmap.stride = chunk_stride;
        image->u.bitmap.palette = 0;
        image->u.bitmap.data = qxl_bo_physical_address(qdev, chunk_bo, 0);
-       qxl_release_add_res(qdev, release, chunk_bo);
-       qxl_bo_unreserve(chunk_bo);
-       qxl_bo_unref(&chunk_bo);
 
-       qxl_bo_kunmap_atomic_page(qdev, *image_bo, ptr);
+       qxl_bo_kunmap_atomic_page(qdev, image_bo, ptr);
 
        return 0;
 }
 
-int qxl_image_create(struct qxl_device *qdev,
+int qxl_image_init(struct qxl_device *qdev,
                     struct qxl_release *release,
-                    struct qxl_bo **image_bo,
+                    struct qxl_drm_image *dimage,
                     const uint8_t *data,
                     int x, int y, int width, int height,
                     int depth, int stride)
 {
        data += y * stride + x * (depth / 8);
-       return qxl_image_create_helper(qdev, release, image_bo, data,
+       return qxl_image_init_helper(qdev, release, dimage, data,
                                       width, height, depth, 0, stride);
 }
index 6cd7273c08041d12b5b394199ad597bbfd8da9dc..7b95c75e9626ae1324dea48b310d3052f0c00d2d 100644 (file)
@@ -68,55 +68,60 @@ static int qxl_map_ioctl(struct drm_device *dev, void *data,
                                  &qxl_map->offset);
 }
 
+struct qxl_reloc_info {
+       int type;
+       struct qxl_bo *dst_bo;
+       uint32_t dst_offset;
+       struct qxl_bo *src_bo;
+       int src_offset;
+};
+
 /*
  * dst must be validated, i.e. whole bo on vram/surfacesram (right now all bo's
  * are on vram).
  * *(dst + dst_off) = qxl_bo_physical_address(src, src_off)
  */
 static void
-apply_reloc(struct qxl_device *qdev, struct qxl_bo *dst, uint64_t dst_off,
-           struct qxl_bo *src, uint64_t src_off)
+apply_reloc(struct qxl_device *qdev, struct qxl_reloc_info *info)
 {
        void *reloc_page;
-
-       reloc_page = qxl_bo_kmap_atomic_page(qdev, dst, dst_off & PAGE_MASK);
-       *(uint64_t *)(reloc_page + (dst_off & ~PAGE_MASK)) = qxl_bo_physical_address(qdev,
-                                                                    src, src_off);
-       qxl_bo_kunmap_atomic_page(qdev, dst, reloc_page);
+       reloc_page = qxl_bo_kmap_atomic_page(qdev, info->dst_bo, info->dst_offset & PAGE_MASK);
+       *(uint64_t *)(reloc_page + (info->dst_offset & ~PAGE_MASK)) = qxl_bo_physical_address(qdev,
+                                                                                             info->src_bo,
+                                                                                             info->src_offset);
+       qxl_bo_kunmap_atomic_page(qdev, info->dst_bo, reloc_page);
 }
 
 static void
-apply_surf_reloc(struct qxl_device *qdev, struct qxl_bo *dst, uint64_t dst_off,
-                struct qxl_bo *src)
+apply_surf_reloc(struct qxl_device *qdev, struct qxl_reloc_info *info)
 {
        uint32_t id = 0;
        void *reloc_page;
 
-       if (src && !src->is_primary)
-               id = src->surface_id;
+       if (info->src_bo && !info->src_bo->is_primary)
+               id = info->src_bo->surface_id;
 
-       reloc_page = qxl_bo_kmap_atomic_page(qdev, dst, dst_off & PAGE_MASK);
-       *(uint32_t *)(reloc_page + (dst_off & ~PAGE_MASK)) = id;
-       qxl_bo_kunmap_atomic_page(qdev, dst, reloc_page);
+       reloc_page = qxl_bo_kmap_atomic_page(qdev, info->dst_bo, info->dst_offset & PAGE_MASK);
+       *(uint32_t *)(reloc_page + (info->dst_offset & ~PAGE_MASK)) = id;
+       qxl_bo_kunmap_atomic_page(qdev, info->dst_bo, reloc_page);
 }
 
 /* return holding the reference to this object */
 static struct qxl_bo *qxlhw_handle_to_bo(struct qxl_device *qdev,
                                         struct drm_file *file_priv, uint64_t handle,
-                                        struct qxl_reloc_list *reloc_list)
+                                        struct qxl_release *release)
 {
        struct drm_gem_object *gobj;
        struct qxl_bo *qobj;
        int ret;
 
        gobj = drm_gem_object_lookup(qdev->ddev, file_priv, handle);
-       if (!gobj) {
-               DRM_ERROR("bad bo handle %lld\n", handle);
+       if (!gobj)
                return NULL;
-       }
+
        qobj = gem_to_qxl_bo(gobj);
 
-       ret = qxl_bo_list_add(reloc_list, qobj);
+       ret = qxl_release_list_add(release, qobj);
        if (ret)
                return NULL;
 
@@ -129,151 +134,177 @@ static struct qxl_bo *qxlhw_handle_to_bo(struct qxl_device *qdev,
  * However, the command as passed from user space must *not* contain the initial
  * QXLReleaseInfo struct (first XXX bytes)
  */
-static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
+static int qxl_process_single_command(struct qxl_device *qdev,
+                                     struct drm_qxl_command *cmd,
+                                     struct drm_file *file_priv)
 {
-       struct qxl_device *qdev = dev->dev_private;
-       struct drm_qxl_execbuffer *execbuffer = data;
-       struct drm_qxl_command user_cmd;
-       int cmd_num;
-       struct qxl_bo *reloc_src_bo;
-       struct qxl_bo *reloc_dst_bo;
-       struct drm_qxl_reloc reloc;
+       struct qxl_reloc_info *reloc_info;
+       int release_type;
+       struct qxl_release *release;
+       struct qxl_bo *cmd_bo;
        void *fb_cmd;
-       int i, ret;
-       struct qxl_reloc_list reloc_list;
+       int i, j, ret, num_relocs;
        int unwritten;
-       uint32_t reloc_dst_offset;
-       INIT_LIST_HEAD(&reloc_list.bos);
 
-       for (cmd_num = 0; cmd_num < execbuffer->commands_num; ++cmd_num) {
-               struct qxl_release *release;
-               struct qxl_bo *cmd_bo;
-               int release_type;
-               struct drm_qxl_command *commands =
-                       (struct drm_qxl_command *)(uintptr_t)execbuffer->commands;
+       switch (cmd->type) {
+       case QXL_CMD_DRAW:
+               release_type = QXL_RELEASE_DRAWABLE;
+               break;
+       case QXL_CMD_SURFACE:
+       case QXL_CMD_CURSOR:
+       default:
+               DRM_DEBUG("Only draw commands in execbuffers\n");
+               return -EINVAL;
+               break;
+       }
 
-               if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num],
-                                      sizeof(user_cmd)))
-                       return -EFAULT;
-               switch (user_cmd.type) {
-               case QXL_CMD_DRAW:
-                       release_type = QXL_RELEASE_DRAWABLE;
-                       break;
-               case QXL_CMD_SURFACE:
-               case QXL_CMD_CURSOR:
-               default:
-                       DRM_DEBUG("Only draw commands in execbuffers\n");
-                       return -EINVAL;
-                       break;
-               }
+       if (cmd->command_size > PAGE_SIZE - sizeof(union qxl_release_info))
+               return -EINVAL;
 
-               if (user_cmd.command_size > PAGE_SIZE - sizeof(union qxl_release_info))
-                       return -EINVAL;
+       if (!access_ok(VERIFY_READ,
+                      (void *)(unsigned long)cmd->command,
+                      cmd->command_size))
+               return -EFAULT;
 
-               if (!access_ok(VERIFY_READ,
-                              (void *)(unsigned long)user_cmd.command,
-                              user_cmd.command_size))
-                       return -EFAULT;
+       reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL);
+       if (!reloc_info)
+               return -ENOMEM;
 
-               ret = qxl_alloc_release_reserved(qdev,
-                                                sizeof(union qxl_release_info) +
-                                                user_cmd.command_size,
-                                                release_type,
-                                                &release,
-                                                &cmd_bo);
-               if (ret)
-                       return ret;
+       ret = qxl_alloc_release_reserved(qdev,
+                                        sizeof(union qxl_release_info) +
+                                        cmd->command_size,
+                                        release_type,
+                                        &release,
+                                        &cmd_bo);
+       if (ret)
+               goto out_free_reloc;
 
-               /* TODO copy slow path code from i915 */
-               fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_SIZE));
-               unwritten = __copy_from_user_inatomic_nocache(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), (void *)(unsigned long)user_cmd.command, user_cmd.command_size);
+       /* TODO copy slow path code from i915 */
+       fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_SIZE));
+       unwritten = __copy_from_user_inatomic_nocache(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_SIZE), (void *)(unsigned long)cmd->command, cmd->command_size);
 
-               {
-                       struct qxl_drawable *draw = fb_cmd;
+       {
+               struct qxl_drawable *draw = fb_cmd;
+               draw->mm_time = qdev->rom->mm_clock;
+       }
 
-                       draw->mm_time = qdev->rom->mm_clock;
-               }
-               qxl_bo_kunmap_atomic_page(qdev, cmd_bo, fb_cmd);
-               if (unwritten) {
-                       DRM_ERROR("got unwritten %d\n", unwritten);
-                       qxl_release_unreserve(qdev, release);
-                       qxl_release_free(qdev, release);
-                       return -EFAULT;
+       qxl_bo_kunmap_atomic_page(qdev, cmd_bo, fb_cmd);
+       if (unwritten) {
+               DRM_ERROR("got unwritten %d\n", unwritten);
+               ret = -EFAULT;
+               goto out_free_release;
+       }
+
+       /* fill out reloc info structs */
+       num_relocs = 0;
+       for (i = 0; i < cmd->relocs_num; ++i) {
+               struct drm_qxl_reloc reloc;
+
+               if (DRM_COPY_FROM_USER(&reloc,
+                                      &((struct drm_qxl_reloc *)(uintptr_t)cmd->relocs)[i],
+                                      sizeof(reloc))) {
+                       ret = -EFAULT;
+                       goto out_free_bos;
                }
 
-               for (i = 0 ; i < user_cmd.relocs_num; ++i) {
-                       if (DRM_COPY_FROM_USER(&reloc,
-                                              &((struct drm_qxl_reloc *)(uintptr_t)user_cmd.relocs)[i],
-                                              sizeof(reloc))) {
-                               qxl_bo_list_unreserve(&reloc_list, true);
-                               qxl_release_unreserve(qdev, release);
-                               qxl_release_free(qdev, release);
-                               return -EFAULT;
-                       }
+               /* add the bos to the list of bos to validate -
+                  need to validate first then process relocs? */
+               if (reloc.reloc_type != QXL_RELOC_TYPE_BO && reloc.reloc_type != QXL_RELOC_TYPE_SURF) {
+                       DRM_DEBUG("unknown reloc type %d\n", reloc_info[i].type);
 
-                       /* add the bos to the list of bos to validate -
-                          need to validate first then process relocs? */
-                       if (reloc.dst_handle) {
-                               reloc_dst_bo = qxlhw_handle_to_bo(qdev, file_priv,
-                                                                 reloc.dst_handle, &reloc_list);
-                               if (!reloc_dst_bo) {
-                                       qxl_bo_list_unreserve(&reloc_list, true);
-                                       qxl_release_unreserve(qdev, release);
-                                       qxl_release_free(qdev, release);
-                                       return -EINVAL;
-                               }
-                               reloc_dst_offset = 0;
-                       } else {
-                               reloc_dst_bo = cmd_bo;
-                               reloc_dst_offset = release->release_offset;
+                       ret = -EINVAL;
+                       goto out_free_bos;
+               }
+               reloc_info[i].type = reloc.reloc_type;
+
+               if (reloc.dst_handle) {
+                       reloc_info[i].dst_bo = qxlhw_handle_to_bo(qdev, file_priv,
+                                                                 reloc.dst_handle, release);
+                       if (!reloc_info[i].dst_bo) {
+                               ret = -EINVAL;
+                               reloc_info[i].src_bo = NULL;
+                               goto out_free_bos;
                        }
-
-                       /* reserve and validate the reloc dst bo */
-                       if (reloc.reloc_type == QXL_RELOC_TYPE_BO || reloc.src_handle > 0) {
-                               reloc_src_bo =
-                                       qxlhw_handle_to_bo(qdev, file_priv,
-                                                          reloc.src_handle, &reloc_list);
-                               if (!reloc_src_bo) {
-                                       if (reloc_dst_bo != cmd_bo)
-                                               drm_gem_object_unreference_unlocked(&reloc_dst_bo->gem_base);
-                                       qxl_bo_list_unreserve(&reloc_list, true);
-                                       qxl_release_unreserve(qdev, release);
-                                       qxl_release_free(qdev, release);
-                                       return -EINVAL;
-                               }
-                       } else
-                               reloc_src_bo = NULL;
-                       if (reloc.reloc_type == QXL_RELOC_TYPE_BO) {
-                               apply_reloc(qdev, reloc_dst_bo, reloc_dst_offset + reloc.dst_offset,
-                                           reloc_src_bo, reloc.src_offset);
-                       } else if (reloc.reloc_type == QXL_RELOC_TYPE_SURF) {
-                               apply_surf_reloc(qdev, reloc_dst_bo, reloc_dst_offset + reloc.dst_offset, reloc_src_bo);
-                       } else {
-                               DRM_ERROR("unknown reloc type %d\n", reloc.reloc_type);
-                               return -EINVAL;
+                       reloc_info[i].dst_offset = reloc.dst_offset;
+               } else {
+                       reloc_info[i].dst_bo = cmd_bo;
+                       reloc_info[i].dst_offset = reloc.dst_offset + release->release_offset;
+               }
+               num_relocs++;
+
+               /* reserve and validate the reloc dst bo */
+               if (reloc.reloc_type == QXL_RELOC_TYPE_BO || reloc.src_handle > 0) {
+                       reloc_info[i].src_bo =
+                               qxlhw_handle_to_bo(qdev, file_priv,
+                                                  reloc.src_handle, release);
+                       if (!reloc_info[i].src_bo) {
+                               if (reloc_info[i].dst_bo != cmd_bo)
+                                       drm_gem_object_unreference_unlocked(&reloc_info[i].dst_bo->gem_base);
+                               ret = -EINVAL;
+                               goto out_free_bos;
                        }
+                       reloc_info[i].src_offset = reloc.src_offset;
+               } else {
+                       reloc_info[i].src_bo = NULL;
+                       reloc_info[i].src_offset = 0;
+               }
+       }
 
-                       if (reloc_src_bo && reloc_src_bo != cmd_bo) {
-                               qxl_release_add_res(qdev, release, reloc_src_bo);
-                               drm_gem_object_unreference_unlocked(&reloc_src_bo->gem_base);
-                       }
+       /* validate all buffers */
+       ret = qxl_release_reserve_list(release, false);
+       if (ret)
+               goto out_free_bos;
 
-                       if (reloc_dst_bo != cmd_bo)
-                               drm_gem_object_unreference_unlocked(&reloc_dst_bo->gem_base);
-               }
-               qxl_fence_releaseable(qdev, release);
+       for (i = 0; i < cmd->relocs_num; ++i) {
+               if (reloc_info[i].type == QXL_RELOC_TYPE_BO)
+                       apply_reloc(qdev, &reloc_info[i]);
+               else if (reloc_info[i].type == QXL_RELOC_TYPE_SURF)
+                       apply_surf_reloc(qdev, &reloc_info[i]);
+       }
 
-               ret = qxl_push_command_ring_release(qdev, release, user_cmd.type, true);
-               if (ret == -ERESTARTSYS) {
-                       qxl_release_unreserve(qdev, release);
-                       qxl_release_free(qdev, release);
-                       qxl_bo_list_unreserve(&reloc_list, true);
+       ret = qxl_push_command_ring_release(qdev, release, cmd->type, true);
+       if (ret)
+               qxl_release_backoff_reserve_list(release);
+       else
+               qxl_release_fence_buffer_objects(release);
+
+out_free_bos:
+       for (j = 0; j < num_relocs; j++) {
+               if (reloc_info[j].dst_bo != cmd_bo)
+                       drm_gem_object_unreference_unlocked(&reloc_info[j].dst_bo->gem_base);
+               if (reloc_info[j].src_bo && reloc_info[j].src_bo != cmd_bo)
+                       drm_gem_object_unreference_unlocked(&reloc_info[j].src_bo->gem_base);
+       }
+out_free_release:
+       if (ret)
+               qxl_release_free(qdev, release);
+out_free_reloc:
+       kfree(reloc_info);
+       return ret;
+}
+
+static int qxl_execbuffer_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       struct qxl_device *qdev = dev->dev_private;
+       struct drm_qxl_execbuffer *execbuffer = data;
+       struct drm_qxl_command user_cmd;
+       int cmd_num;
+       int ret;
+
+       for (cmd_num = 0; cmd_num < execbuffer->commands_num; ++cmd_num) {
+
+               struct drm_qxl_command *commands =
+                       (struct drm_qxl_command *)(uintptr_t)execbuffer->commands;
+
+               if (DRM_COPY_FROM_USER(&user_cmd, &commands[cmd_num],
+                                      sizeof(user_cmd)))
+                       return -EFAULT;
+
+               ret = qxl_process_single_command(qdev, &user_cmd, file_priv);
+               if (ret)
                        return ret;
-               }
-               qxl_release_unreserve(qdev, release);
        }
-       qxl_bo_list_unreserve(&reloc_list, 0);
        return 0;
 }
 
@@ -305,7 +336,7 @@ static int qxl_update_area_ioctl(struct drm_device *dev, void *data,
                goto out;
 
        if (!qobj->pin_count) {
-               qxl_ttm_placement_from_domain(qobj, qobj->type);
+               qxl_ttm_placement_from_domain(qobj, qobj->type, false);
                ret = ttm_bo_validate(&qobj->tbo, &qobj->placement,
                                      true, false);
                if (unlikely(ret))
index 1191fe7788c932d6c10e678815724c1dd44b8f16..aa161cddd87e4a018c601e25e722663d4e0e3207 100644 (file)
@@ -51,20 +51,21 @@ bool qxl_ttm_bo_is_qxl_bo(struct ttm_buffer_object *bo)
        return false;
 }
 
-void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
+void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain, bool pinned)
 {
        u32 c = 0;
+       u32 pflag = pinned ? TTM_PL_FLAG_NO_EVICT : 0;
 
        qbo->placement.fpfn = 0;
        qbo->placement.lpfn = 0;
        qbo->placement.placement = qbo->placements;
        qbo->placement.busy_placement = qbo->placements;
        if (domain == QXL_GEM_DOMAIN_VRAM)
-               qbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM;
+               qbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM | pflag;
        if (domain == QXL_GEM_DOMAIN_SURFACE)
-               qbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_PRIV0;
+               qbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_PRIV0 | pflag;
        if (domain == QXL_GEM_DOMAIN_CPU)
-               qbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+               qbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM | pflag;
        if (!c)
                qbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
        qbo->placement.num_placement = c;
@@ -73,7 +74,7 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain)
 
 
 int qxl_bo_create(struct qxl_device *qdev,
-                 unsigned long size, bool kernel, u32 domain,
+                 unsigned long size, bool kernel, bool pinned, u32 domain,
                  struct qxl_surface *surf,
                  struct qxl_bo **bo_ptr)
 {
@@ -99,15 +100,15 @@ int qxl_bo_create(struct qxl_device *qdev,
        }
        bo->gem_base.driver_private = NULL;
        bo->type = domain;
-       bo->pin_count = 0;
+       bo->pin_count = pinned ? 1 : 0;
        bo->surface_id = 0;
        qxl_fence_init(qdev, &bo->fence);
        INIT_LIST_HEAD(&bo->list);
-       atomic_set(&bo->reserve_count, 0);
+
        if (surf)
                bo->surf = *surf;
 
-       qxl_ttm_placement_from_domain(bo, domain);
+       qxl_ttm_placement_from_domain(bo, domain, pinned);
 
        r = ttm_bo_init(&qdev->mman.bdev, &bo->tbo, size, type,
                        &bo->placement, 0, !kernel, NULL, size,
@@ -228,7 +229,7 @@ struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo)
 int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr)
 {
        struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
-       int r, i;
+       int r;
 
        if (bo->pin_count) {
                bo->pin_count++;
@@ -236,9 +237,7 @@ int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr)
                        *gpu_addr = qxl_bo_gpu_offset(bo);
                return 0;
        }
-       qxl_ttm_placement_from_domain(bo, domain);
-       for (i = 0; i < bo->placement.num_placement; i++)
-               bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
+       qxl_ttm_placement_from_domain(bo, domain, true);
        r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
        if (likely(r == 0)) {
                bo->pin_count = 1;
@@ -317,53 +316,6 @@ int qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo)
        return 0;
 }
 
-void qxl_bo_list_unreserve(struct qxl_reloc_list *reloc_list, bool failed)
-{
-       struct qxl_bo_list *entry, *sf;
-
-       list_for_each_entry_safe(entry, sf, &reloc_list->bos, lhead) {
-               qxl_bo_unreserve(entry->bo);
-               list_del(&entry->lhead);
-               kfree(entry);
-       }
-}
-
-int qxl_bo_list_add(struct qxl_reloc_list *reloc_list, struct qxl_bo *bo)
-{
-       struct qxl_bo_list *entry;
-       int ret;
-
-       list_for_each_entry(entry, &reloc_list->bos, lhead) {
-               if (entry->bo == bo)
-                       return 0;
-       }
-
-       entry = kmalloc(sizeof(struct qxl_bo_list), GFP_KERNEL);
-       if (!entry)
-               return -ENOMEM;
-
-       entry->bo = bo;
-       list_add(&entry->lhead, &reloc_list->bos);
-
-       ret = qxl_bo_reserve(bo, false);
-       if (ret)
-               return ret;
-
-       if (!bo->pin_count) {
-               qxl_ttm_placement_from_domain(bo, bo->type);
-               ret = ttm_bo_validate(&bo->tbo, &bo->placement,
-                                     true, false);
-               if (ret)
-                       return ret;
-       }
-
-       /* allocate a surface for reserved + validated buffers */
-       ret = qxl_bo_check_id(bo->gem_base.dev->dev_private, bo);
-       if (ret)
-               return ret;
-       return 0;
-}
-
 int qxl_surf_evict(struct qxl_device *qdev)
 {
        return ttm_bo_evict_mm(&qdev->mman.bdev, TTM_PL_PRIV0);
index af10165adb0d49570980fc849b312d0abb9f24a0..d458a140c02407c01858f2d7b8a212e80417db3a 100644 (file)
@@ -88,7 +88,7 @@ static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type,
 
 extern int qxl_bo_create(struct qxl_device *qdev,
                         unsigned long size,
-                        bool kernel, u32 domain,
+                        bool kernel, bool pinned, u32 domain,
                         struct qxl_surface *surf,
                         struct qxl_bo **bo_ptr);
 extern int qxl_bo_kmap(struct qxl_bo *bo, void **ptr);
@@ -99,9 +99,7 @@ extern struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo);
 extern void qxl_bo_unref(struct qxl_bo **bo);
 extern int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr);
 extern int qxl_bo_unpin(struct qxl_bo *bo);
-extern void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain);
+extern void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain, bool pinned);
 extern bool qxl_ttm_bo_is_qxl_bo(struct ttm_buffer_object *bo);
 
-extern int qxl_bo_list_add(struct qxl_reloc_list *reloc_list, struct qxl_bo *bo);
-extern void qxl_bo_list_unreserve(struct qxl_reloc_list *reloc_list, bool failed);
 #endif
index 1a648e1da6a6ac7f295fc6418e5ad8873b08236a..0109a9644cb29ef7a6e13ac76a90544effcefd20 100644 (file)
@@ -38,7 +38,8 @@
 
 static const int release_size_per_bo[] = { RELEASE_SIZE, SURFACE_RELEASE_SIZE, RELEASE_SIZE };
 static const int releases_per_bo[] = { RELEASES_PER_BO, SURFACE_RELEASES_PER_BO, RELEASES_PER_BO };
-uint64_t
+
+static uint64_t
 qxl_release_alloc(struct qxl_device *qdev, int type,
                  struct qxl_release **ret)
 {
@@ -53,9 +54,9 @@ qxl_release_alloc(struct qxl_device *qdev, int type,
                return 0;
        }
        release->type = type;
-       release->bo_count = 0;
        release->release_offset = 0;
        release->surface_release_id = 0;
+       INIT_LIST_HEAD(&release->bos);
 
        idr_preload(GFP_KERNEL);
        spin_lock(&qdev->release_idr_lock);
@@ -77,20 +78,20 @@ void
 qxl_release_free(struct qxl_device *qdev,
                 struct qxl_release *release)
 {
-       int i;
-
-       QXL_INFO(qdev, "release %d, type %d, %d bos\n", release->id,
-                release->type, release->bo_count);
+       struct qxl_bo_list *entry, *tmp;
+       QXL_INFO(qdev, "release %d, type %d\n", release->id,
+                release->type);
 
        if (release->surface_release_id)
                qxl_surface_id_dealloc(qdev, release->surface_release_id);
 
-       for (i = 0 ; i < release->bo_count; ++i) {
+       list_for_each_entry_safe(entry, tmp, &release->bos, tv.head) {
+               struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
                QXL_INFO(qdev, "release %llx\n",
-                       drm_vma_node_offset_addr(&release->bos[i]->tbo.vma_node)
+                       drm_vma_node_offset_addr(&entry->tv.bo->vma_node)
                                                - DRM_FILE_OFFSET);
-               qxl_fence_remove_release(&release->bos[i]->fence, release->id);
-               qxl_bo_unref(&release->bos[i]);
+               qxl_fence_remove_release(&bo->fence, release->id);
+               qxl_bo_unref(&bo);
        }
        spin_lock(&qdev->release_idr_lock);
        idr_remove(&qdev->release_idr, release->id);
@@ -98,83 +99,117 @@ qxl_release_free(struct qxl_device *qdev,
        kfree(release);
 }
 
-void
-qxl_release_add_res(struct qxl_device *qdev, struct qxl_release *release,
-                   struct qxl_bo *bo)
-{
-       int i;
-       for (i = 0; i < release->bo_count; i++)
-               if (release->bos[i] == bo)
-                       return;
-
-       if (release->bo_count >= QXL_MAX_RES) {
-               DRM_ERROR("exceeded max resource on a qxl_release item\n");
-               return;
-       }
-       release->bos[release->bo_count++] = qxl_bo_ref(bo);
-}
-
 static int qxl_release_bo_alloc(struct qxl_device *qdev,
                                struct qxl_bo **bo)
 {
        int ret;
-       ret = qxl_bo_create(qdev, PAGE_SIZE, false, QXL_GEM_DOMAIN_VRAM, NULL,
+       /* pin releases bo's they are too messy to evict */
+       ret = qxl_bo_create(qdev, PAGE_SIZE, false, true,
+                           QXL_GEM_DOMAIN_VRAM, NULL,
                            bo);
        return ret;
 }
 
-int qxl_release_reserve(struct qxl_device *qdev,
-                       struct qxl_release *release, bool no_wait)
+int qxl_release_list_add(struct qxl_release *release, struct qxl_bo *bo)
+{
+       struct qxl_bo_list *entry;
+
+       list_for_each_entry(entry, &release->bos, tv.head) {
+               if (entry->tv.bo == &bo->tbo)
+                       return 0;
+       }
+
+       entry = kmalloc(sizeof(struct qxl_bo_list), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       qxl_bo_ref(bo);
+       entry->tv.bo = &bo->tbo;
+       list_add_tail(&entry->tv.head, &release->bos);
+       return 0;
+}
+
+static int qxl_release_validate_bo(struct qxl_bo *bo)
 {
        int ret;
-       if (atomic_inc_return(&release->bos[0]->reserve_count) == 1) {
-               ret = qxl_bo_reserve(release->bos[0], no_wait);
+
+       if (!bo->pin_count) {
+               qxl_ttm_placement_from_domain(bo, bo->type, false);
+               ret = ttm_bo_validate(&bo->tbo, &bo->placement,
+                                     true, false);
                if (ret)
                        return ret;
        }
+
+       /* allocate a surface for reserved + validated buffers */
+       ret = qxl_bo_check_id(bo->gem_base.dev->dev_private, bo);
+       if (ret)
+               return ret;
+       return 0;
+}
+
+int qxl_release_reserve_list(struct qxl_release *release, bool no_intr)
+{
+       int ret;
+       struct qxl_bo_list *entry;
+
+       /* if only one object on the release its the release itself
+          since these objects are pinned no need to reserve */
+       if (list_is_singular(&release->bos))
+               return 0;
+
+       ret = ttm_eu_reserve_buffers(&release->ticket, &release->bos);
+       if (ret)
+               return ret;
+
+       list_for_each_entry(entry, &release->bos, tv.head) {
+               struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
+
+               ret = qxl_release_validate_bo(bo);
+               if (ret) {
+                       ttm_eu_backoff_reservation(&release->ticket, &release->bos);
+                       return ret;
+               }
+       }
        return 0;
 }
 
-void qxl_release_unreserve(struct qxl_device *qdev,
-                         struct qxl_release *release)
+void qxl_release_backoff_reserve_list(struct qxl_release *release)
 {
-       if (atomic_dec_and_test(&release->bos[0]->reserve_count))
-               qxl_bo_unreserve(release->bos[0]);
+       /* if only one object on the release its the release itself
+          since these objects are pinned no need to reserve */
+       if (list_is_singular(&release->bos))
+               return;
+
+       ttm_eu_backoff_reservation(&release->ticket, &release->bos);
 }
 
+
 int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
                                       enum qxl_surface_cmd_type surface_cmd_type,
                                       struct qxl_release *create_rel,
                                       struct qxl_release **release)
 {
-       int ret;
-
        if (surface_cmd_type == QXL_SURFACE_CMD_DESTROY && create_rel) {
                int idr_ret;
+               struct qxl_bo_list *entry = list_first_entry(&create_rel->bos, struct qxl_bo_list, tv.head);
                struct qxl_bo *bo;
                union qxl_release_info *info;
 
                /* stash the release after the create command */
                idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
-               bo = qxl_bo_ref(create_rel->bos[0]);
+               bo = qxl_bo_ref(to_qxl_bo(entry->tv.bo));
 
                (*release)->release_offset = create_rel->release_offset + 64;
 
-               qxl_release_add_res(qdev, *release, bo);
+               qxl_release_list_add(*release, bo);
 
-               ret = qxl_release_reserve(qdev, *release, false);
-               if (ret) {
-                       DRM_ERROR("release reserve failed\n");
-                       goto out_unref;
-               }
                info = qxl_release_map(qdev, *release);
                info->id = idr_ret;
                qxl_release_unmap(qdev, *release, info);
 
-
-out_unref:
                qxl_bo_unref(&bo);
-               return ret;
+               return 0;
        }
 
        return qxl_alloc_release_reserved(qdev, sizeof(struct qxl_surface_cmd),
@@ -187,7 +222,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
 {
        struct qxl_bo *bo;
        int idr_ret;
-       int ret;
+       int ret = 0;
        union qxl_release_info *info;
        int cur_idx;
 
@@ -216,11 +251,6 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
                        mutex_unlock(&qdev->release_mutex);
                        return ret;
                }
-
-               /* pin releases bo's they are too messy to evict */
-               ret = qxl_bo_reserve(qdev->current_release_bo[cur_idx], false);
-               qxl_bo_pin(qdev->current_release_bo[cur_idx], QXL_GEM_DOMAIN_VRAM, NULL);
-               qxl_bo_unreserve(qdev->current_release_bo[cur_idx]);
        }
 
        bo = qxl_bo_ref(qdev->current_release_bo[cur_idx]);
@@ -231,36 +261,18 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
        if (rbo)
                *rbo = bo;
 
-       qxl_release_add_res(qdev, *release, bo);
-
-       ret = qxl_release_reserve(qdev, *release, false);
        mutex_unlock(&qdev->release_mutex);
-       if (ret)
-               goto out_unref;
+
+       qxl_release_list_add(*release, bo);
 
        info = qxl_release_map(qdev, *release);
        info->id = idr_ret;
        qxl_release_unmap(qdev, *release, info);
 
-out_unref:
        qxl_bo_unref(&bo);
        return ret;
 }
 
-int qxl_fence_releaseable(struct qxl_device *qdev,
-                         struct qxl_release *release)
-{
-       int i, ret;
-       for (i = 0; i < release->bo_count; i++) {
-               if (!release->bos[i]->tbo.sync_obj)
-                       release->bos[i]->tbo.sync_obj = &release->bos[i]->fence;
-               ret = qxl_fence_add_release(&release->bos[i]->fence, release->id);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
 struct qxl_release *qxl_release_from_id_locked(struct qxl_device *qdev,
                                                   uint64_t id)
 {
@@ -273,10 +285,7 @@ struct qxl_release *qxl_release_from_id_locked(struct qxl_device *qdev,
                DRM_ERROR("failed to find id in release_idr\n");
                return NULL;
        }
-       if (release->bo_count < 1) {
-               DRM_ERROR("read a released resource with 0 bos\n");
-               return NULL;
-       }
+
        return release;
 }
 
@@ -285,9 +294,12 @@ union qxl_release_info *qxl_release_map(struct qxl_device *qdev,
 {
        void *ptr;
        union qxl_release_info *info;
-       struct qxl_bo *bo = release->bos[0];
+       struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head);
+       struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
 
        ptr = qxl_bo_kmap_atomic_page(qdev, bo, release->release_offset & PAGE_SIZE);
+       if (!ptr)
+               return NULL;
        info = ptr + (release->release_offset & ~PAGE_SIZE);
        return info;
 }
@@ -296,9 +308,51 @@ void qxl_release_unmap(struct qxl_device *qdev,
                       struct qxl_release *release,
                       union qxl_release_info *info)
 {
-       struct qxl_bo *bo = release->bos[0];
+       struct qxl_bo_list *entry = list_first_entry(&release->bos, struct qxl_bo_list, tv.head);
+       struct qxl_bo *bo = to_qxl_bo(entry->tv.bo);
        void *ptr;
 
        ptr = ((void *)info) - (release->release_offset & ~PAGE_SIZE);
        qxl_bo_kunmap_atomic_page(qdev, bo, ptr);
 }
+
+void qxl_release_fence_buffer_objects(struct qxl_release *release)
+{
+       struct ttm_validate_buffer *entry;
+       struct ttm_buffer_object *bo;
+       struct ttm_bo_global *glob;
+       struct ttm_bo_device *bdev;
+       struct ttm_bo_driver *driver;
+       struct qxl_bo *qbo;
+
+       /* if only one object on the release its the release itself
+          since these objects are pinned no need to reserve */
+       if (list_is_singular(&release->bos))
+               return;
+
+       bo = list_first_entry(&release->bos, struct ttm_validate_buffer, head)->bo;
+       bdev = bo->bdev;
+       driver = bdev->driver;
+       glob = bo->glob;
+
+       spin_lock(&glob->lru_lock);
+       spin_lock(&bdev->fence_lock);
+
+       list_for_each_entry(entry, &release->bos, head) {
+               bo = entry->bo;
+               qbo = to_qxl_bo(bo);
+
+               if (!entry->bo->sync_obj)
+                       entry->bo->sync_obj = &qbo->fence;
+
+               qxl_fence_add_release_locked(&qbo->fence, release->id);
+
+               ttm_bo_add_to_lru(bo);
+               ww_mutex_unlock(&bo->resv->lock);
+               entry->reserved = false;
+       }
+       spin_unlock(&bdev->fence_lock);
+       spin_unlock(&glob->lru_lock);
+       ww_acquire_fini(&release->ticket);
+}
+
index 489cb8cece4da553b9f5c36c4dc9c610e617c3ea..1dfd84cda2a128e39f4e8143c43b3d0c6a99f30b 100644 (file)
@@ -206,7 +206,7 @@ static void qxl_evict_flags(struct ttm_buffer_object *bo,
                return;
        }
        qbo = container_of(bo, struct qxl_bo, tbo);
-       qxl_ttm_placement_from_domain(qbo, QXL_GEM_DOMAIN_CPU);
+       qxl_ttm_placement_from_domain(qbo, QXL_GEM_DOMAIN_CPU, false);
        *placement = qbo->placement;
 }
 
index c239739736db5f047e495af913b8e7334e9cc2f7..3569d89b9e41c9c69250bffc8b75fce591b69653 100644 (file)
@@ -44,6 +44,41 @@ static char *pre_emph_names[] = {
 };
 
 /***** radeon AUX functions *****/
+
+/* Atom needs data in little endian format
+ * so swap as appropriate when copying data to
+ * or from atom. Note that atom operates on
+ * dw units.
+ */
+static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
+{
+#ifdef __BIG_ENDIAN
+       u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
+       u32 *dst32, *src32;
+       int i;
+
+       memcpy(src_tmp, src, num_bytes);
+       src32 = (u32 *)src_tmp;
+       dst32 = (u32 *)dst_tmp;
+       if (to_le) {
+               for (i = 0; i < ((num_bytes + 3) / 4); i++)
+                       dst32[i] = cpu_to_le32(src32[i]);
+               memcpy(dst, dst_tmp, num_bytes);
+       } else {
+               u8 dws = num_bytes & ~3;
+               for (i = 0; i < ((num_bytes + 3) / 4); i++)
+                       dst32[i] = le32_to_cpu(src32[i]);
+               memcpy(dst, dst_tmp, dws);
+               if (num_bytes % 4) {
+                       for (i = 0; i < (num_bytes % 4); i++)
+                               dst[dws+i] = dst_tmp[dws+i];
+               }
+       }
+#else
+       memcpy(dst, src, num_bytes);
+#endif
+}
+
 union aux_channel_transaction {
        PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
        PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
@@ -65,10 +100,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
 
        base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
 
-       memcpy(base, send, send_bytes);
+       radeon_copy_swap(base, send, send_bytes, true);
 
-       args.v1.lpAuxRequest = 0 + 4;
-       args.v1.lpDataOut = 16 + 4;
+       args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4));
+       args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4));
        args.v1.ucDataOutLen = 0;
        args.v1.ucChannelID = chan->rec.i2c_id;
        args.v1.ucDelay = delay / 10;
@@ -102,7 +137,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
                recv_bytes = recv_size;
 
        if (recv && recv_size)
-               memcpy(recv, base + 16, recv_bytes);
+               radeon_copy_swap(recv, base + 16, recv_bytes, false);
 
        return recv_bytes;
 }
index 319e1ee1844aa4ac128b64941d06ddaf23d0d97c..cfc1d28ade39e4d39329feee29dd8a63de410c66 100644 (file)
@@ -3166,7 +3166,7 @@ int r600_copy_cpdma(struct radeon_device *rdev,
 
        size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT);
        num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff);
-       r = radeon_ring_lock(rdev, ring, num_loops * 6 + 21);
+       r = radeon_ring_lock(rdev, ring, num_loops * 6 + 24);
        if (r) {
                DRM_ERROR("radeon: moving bo (%d).\n", r);
                radeon_semaphore_free(rdev, &sem, NULL);
@@ -3181,6 +3181,9 @@ int r600_copy_cpdma(struct radeon_device *rdev,
                radeon_semaphore_free(rdev, &sem, NULL);
        }
 
+       radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+       radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
+       radeon_ring_write(ring, WAIT_3D_IDLE_bit);
        for (i = 0; i < num_loops; i++) {
                cur_size_in_bytes = size_in_bytes;
                if (cur_size_in_bytes > 0x1fffff)
index b88f54b134abaa838b44dc0a5e614df2c06f3be5..e5c860f4ccbe4f7641745c018b6dda9650a4a5e7 100644 (file)
@@ -278,9 +278,9 @@ bool r600_dynamicpm_enabled(struct radeon_device *rdev)
 void r600_enable_sclk_control(struct radeon_device *rdev, bool enable)
 {
        if (enable)
-               WREG32_P(GENERAL_PWRMGT, 0, ~SCLK_PWRMGT_OFF);
+               WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
        else
-               WREG32_P(GENERAL_PWRMGT, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
+               WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
 }
 
 void r600_enable_mclk_control(struct radeon_device *rdev, bool enable)
index 78bec1a58ed1a70be65e9bd11bc235fcded90df6..f8f8b3113dddd140bb6bc51455dc86307cc267e3 100644 (file)
@@ -1161,6 +1161,7 @@ static struct radeon_asic rv6xx_asic = {
                .get_mclk = &rv6xx_dpm_get_mclk,
                .print_power_state = &rv6xx_dpm_print_power_state,
                .debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level,
+               .force_performance_level = &rv6xx_dpm_force_performance_level,
        },
        .pflip = {
                .pre_page_flip = &rs600_pre_page_flip,
index ca1895709908b428bdc078c36abc5e40a19e6d73..902479fa737ff62c1b2917b4d0bfce0c34176d74 100644 (file)
@@ -421,6 +421,8 @@ void rv6xx_dpm_print_power_state(struct radeon_device *rdev,
                                 struct radeon_ps *ps);
 void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
                                                       struct seq_file *m);
+int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
+                                     enum radeon_dpm_forced_level level);
 /* rs780 dpm */
 int rs780_dpm_init(struct radeon_device *rdev);
 int rs780_dpm_enable(struct radeon_device *rdev);
index 78edadc9e86b22b8ec64d5877f4b98365cafcffd..68ce360560190af6505856452658e450d3f6878a 100644 (file)
@@ -147,7 +147,7 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
                                         enum radeon_combios_table_offset table)
 {
        struct radeon_device *rdev = dev->dev_private;
-       int rev;
+       int rev, size;
        uint16_t offset = 0, check_offset;
 
        if (!rdev->bios)
@@ -156,174 +156,106 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
        switch (table) {
                /* absolute offset tables */
        case COMBIOS_ASIC_INIT_1_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0xc);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0xc;
                break;
        case COMBIOS_BIOS_SUPPORT_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x14);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x14;
                break;
        case COMBIOS_DAC_PROGRAMMING_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x2a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x2a;
                break;
        case COMBIOS_MAX_COLOR_DEPTH_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x2c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x2c;
                break;
        case COMBIOS_CRTC_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x2e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x2e;
                break;
        case COMBIOS_PLL_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x30);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x30;
                break;
        case COMBIOS_TV_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x32);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x32;
                break;
        case COMBIOS_DFP_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x34);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x34;
                break;
        case COMBIOS_HW_CONFIG_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x36);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x36;
                break;
        case COMBIOS_MULTIMEDIA_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x38);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x38;
                break;
        case COMBIOS_TV_STD_PATCH_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x3e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x3e;
                break;
        case COMBIOS_LCD_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x40);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x40;
                break;
        case COMBIOS_MOBILE_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x42);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x42;
                break;
        case COMBIOS_PLL_INIT_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x46);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x46;
                break;
        case COMBIOS_MEM_CONFIG_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x48);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x48;
                break;
        case COMBIOS_SAVE_MASK_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x4a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x4a;
                break;
        case COMBIOS_HARDCODED_EDID_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x4c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x4c;
                break;
        case COMBIOS_ASIC_INIT_2_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x4e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x4e;
                break;
        case COMBIOS_CONNECTOR_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x50);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x50;
                break;
        case COMBIOS_DYN_CLK_1_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x52);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x52;
                break;
        case COMBIOS_RESERVED_MEM_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x54);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x54;
                break;
        case COMBIOS_EXT_TMDS_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x58);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x58;
                break;
        case COMBIOS_MEM_CLK_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x5a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x5a;
                break;
        case COMBIOS_EXT_DAC_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x5c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x5c;
                break;
        case COMBIOS_MISC_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x5e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x5e;
                break;
        case COMBIOS_CRT_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x60);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x60;
                break;
        case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x62);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x62;
                break;
        case COMBIOS_COMPONENT_VIDEO_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x64);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x64;
                break;
        case COMBIOS_FAN_SPEED_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x66);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x66;
                break;
        case COMBIOS_OVERDRIVE_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x68);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x68;
                break;
        case COMBIOS_OEM_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x6a);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x6a;
                break;
        case COMBIOS_DYN_CLK_2_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x6c);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x6c;
                break;
        case COMBIOS_POWER_CONNECTOR_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x6e);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x6e;
                break;
        case COMBIOS_I2C_INFO_TABLE:
-               check_offset = RBIOS16(rdev->bios_header_start + 0x70);
-               if (check_offset)
-                       offset = check_offset;
+               check_offset = 0x70;
                break;
                /* relative offset tables */
        case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */
@@ -439,11 +371,16 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
                }
                break;
        default:
+               check_offset = 0;
                break;
        }
 
-       return offset;
+       size = RBIOS8(rdev->bios_header_start + 0x6);
+       /* check absolute offset tables */
+       if (table < COMBIOS_ASIC_INIT_3_TABLE && check_offset && check_offset < size)
+               offset = RBIOS16(rdev->bios_header_start + check_offset);
 
+       return offset;
 }
 
 bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
@@ -965,16 +902,22 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
                        dac = RBIOS8(dac_info + 0x3) & 0xf;
                        p_dac->ps2_pdac_adj = (bg << 8) | (dac);
                }
-               /* if the values are all zeros, use the table */
-               if (p_dac->ps2_pdac_adj)
+               /* if the values are zeros, use the table */
+               if ((dac == 0) || (bg == 0))
+                       found = 0;
+               else
                        found = 1;
        }
 
        /* quirks */
+       /* Radeon 7000 (RV100) */
+       if (((dev->pdev->device == 0x5159) &&
+           (dev->pdev->subsystem_vendor == 0x174B) &&
+           (dev->pdev->subsystem_device == 0x7c28)) ||
        /* Radeon 9100 (R200) */
-       if ((dev->pdev->device == 0x514D) &&
+          ((dev->pdev->device == 0x514D) &&
            (dev->pdev->subsystem_vendor == 0x174B) &&
-           (dev->pdev->subsystem_device == 0x7149)) {
+           (dev->pdev->subsystem_device == 0x7149))) {
                /* vbios value is bad, use the default */
                found = 0;
        }
index d9d31a3832769d0363b2d0a728f9e3d7a76add98..6a51d943ccf44d8301758a4b99e3aba35e4c2668 100644 (file)
@@ -466,7 +466,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
                size += rdev->vm_manager.max_pfn * 8;
                size *= 2;
                r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager,
-                                             RADEON_VM_PTB_ALIGN(size),
+                                             RADEON_GPU_PAGE_ALIGN(size),
                                              RADEON_VM_PTB_ALIGN_SIZE,
                                              RADEON_GEM_DOMAIN_VRAM);
                if (r) {
@@ -621,7 +621,7 @@ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm)
        }
 
 retry:
-       pd_size = RADEON_VM_PTB_ALIGN(radeon_vm_directory_size(rdev));
+       pd_size = radeon_vm_directory_size(rdev);
        r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
                             &vm->page_directory, pd_size,
                             RADEON_VM_PTB_ALIGN_SIZE, false);
@@ -953,8 +953,8 @@ static int radeon_vm_update_pdes(struct radeon_device *rdev,
 retry:
                r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
                                     &vm->page_tables[pt_idx],
-                                    RADEON_VM_PTB_ALIGN(RADEON_VM_PTE_COUNT * 8),
-                                    RADEON_VM_PTB_ALIGN_SIZE, false);
+                                    RADEON_VM_PTE_COUNT * 8,
+                                    RADEON_GPU_PAGE_SIZE, false);
 
                if (r == -ENOMEM) {
                        r = radeon_vm_evict(rdev, vm);
index 65e33f38734130043dbdc061c57c70d9006b2e6e..363018c60412c1d7374ee60a176abe2f5c49dce7 100644 (file)
@@ -819,7 +819,7 @@ static void rv6xx_program_memory_timing_parameters(struct radeon_device *rdev)
                 POWERMODE1(calculate_memory_refresh_rate(rdev,
                                                          pi->hw.sclks[R600_POWER_LEVEL_MEDIUM])) |
                 POWERMODE2(calculate_memory_refresh_rate(rdev,
-                                                         pi->hw.sclks[R600_POWER_LEVEL_MEDIUM])) |
+                                                         pi->hw.sclks[R600_POWER_LEVEL_HIGH])) |
                 POWERMODE3(calculate_memory_refresh_rate(rdev,
                                                          pi->hw.sclks[R600_POWER_LEVEL_HIGH])));
        WREG32(ARB_RFSH_RATE, arb_refresh_rate);
@@ -1182,10 +1182,10 @@ static void rv6xx_program_display_gap(struct radeon_device *rdev)
        u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
 
        tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
-       if (RREG32(AVIVO_D1CRTC_CONTROL) & AVIVO_CRTC_EN) {
+       if (rdev->pm.dpm.new_active_crtcs & 1) {
                tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
                tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
-       } else if (RREG32(AVIVO_D2CRTC_CONTROL) & AVIVO_CRTC_EN) {
+       } else if (rdev->pm.dpm.new_active_crtcs & 2) {
                tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
                tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
        } else {
@@ -1670,6 +1670,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
        struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
        int ret;
 
+       pi->restricted_levels = 0;
+
        rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 
        rv6xx_clear_vc(rdev);
@@ -1756,6 +1758,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 
        rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
+       rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
+
        return 0;
 }
 
@@ -2085,3 +2089,34 @@ u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low)
        else
                return requested_state->high.mclk;
 }
+
+int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
+                                     enum radeon_dpm_forced_level level)
+{
+       struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
+
+       if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
+               pi->restricted_levels = 3;
+       } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
+               pi->restricted_levels = 2;
+       } else {
+               pi->restricted_levels = 0;
+       }
+
+       rv6xx_clear_vc(rdev);
+       r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true);
+       r600_set_at(rdev, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
+       r600_wait_for_power_level(rdev, R600_POWER_LEVEL_LOW);
+       r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false);
+       r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false);
+       rv6xx_enable_medium(rdev);
+       rv6xx_enable_high(rdev);
+       if (pi->restricted_levels == 3)
+               r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, false);
+       rv6xx_program_vc(rdev);
+       rv6xx_program_at(rdev);
+
+       rdev->pm.dpm.forced_level = level;
+
+       return 0;
+}
index 72887df8dd76a698e49b9d7cd95401cf52913e00..c590cd9dca0bc5d707bf1c8a2fdce62fb3946d59 100644 (file)
@@ -7,3 +7,10 @@ config DRM_RCAR_DU
        help
          Choose this option if you have an R-Car chipset.
          If M is selected the module will be called rcar-du-drm.
+
+config DRM_RCAR_LVDS
+       bool "R-Car DU LVDS Encoder Support"
+       depends on DRM_RCAR_DU
+       help
+         Enable support the R-Car Display Unit embedded LVDS encoders
+         (currently only on R8A7790).
index 7333c0094015ce45bc7dd541082dd6d439be6425..12b8d447783538518e491d34cfca1fc87a9a3683 100644 (file)
@@ -1,8 +1,12 @@
 rcar-du-drm-y := rcar_du_crtc.o \
                 rcar_du_drv.o \
+                rcar_du_encoder.o \
+                rcar_du_group.o \
                 rcar_du_kms.o \
-                rcar_du_lvds.o \
+                rcar_du_lvdscon.o \
                 rcar_du_plane.o \
-                rcar_du_vga.o
+                rcar_du_vgacon.o
 
-obj-$(CONFIG_DRM_RCAR_DU)      += rcar-du-drm.o
+rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)    += rcar_du_lvdsenc.o
+
+obj-$(CONFIG_DRM_RCAR_DU)              += rcar-du-drm.o
index 24183fb935927851034998ddca26e63a9e820ba3..33df7a5831438092e16116d5594e38d2b8004e33 100644 (file)
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
 #include "rcar_du_kms.h"
-#include "rcar_du_lvds.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
-#include "rcar_du_vga.h"
-
-#define to_rcar_crtc(c)        container_of(c, struct rcar_du_crtc, crtc)
 
 static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
 
        return rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
 }
 
 static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
 
        rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data);
 }
 
 static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
 
        rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
                      rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr);
@@ -54,7 +50,7 @@ static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
 
 static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
 
        rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
                      rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
@@ -63,29 +59,48 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
 static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
                                 u32 clr, u32 set)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
        u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
 
        rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
 }
 
+static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
+{
+       int ret;
+
+       ret = clk_prepare_enable(rcrtc->clock);
+       if (ret < 0)
+               return ret;
+
+       ret = rcar_du_group_get(rcrtc->group);
+       if (ret < 0)
+               clk_disable_unprepare(rcrtc->clock);
+
+       return ret;
+}
+
+static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
+{
+       rcar_du_group_put(rcrtc->group);
+       clk_disable_unprepare(rcrtc->clock);
+}
+
 static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 {
-       struct drm_crtc *crtc = &rcrtc->crtc;
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
-       const struct drm_display_mode *mode = &crtc->mode;
+       const struct drm_display_mode *mode = &rcrtc->crtc.mode;
        unsigned long clk;
        u32 value;
        u32 div;
 
        /* Dot clock */
-       clk = clk_get_rate(rcdu->clock);
+       clk = clk_get_rate(rcrtc->clock);
        div = DIV_ROUND_CLOSEST(clk, mode->clock * 1000);
        div = clamp(div, 1U, 64U) - 1;
 
-       rcar_du_write(rcdu, rcrtc->index ? ESCR2 : ESCR,
-                     ESCR_DCLKSEL_CLKS | div);
-       rcar_du_write(rcdu, rcrtc->index ? OTAR2 : OTAR, 0);
+       rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR,
+                           ESCR_DCLKSEL_CLKS | div);
+       rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
 
        /* Signal polarities */
        value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
@@ -112,68 +127,25 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
        rcar_du_crtc_write(rcrtc, DEWR,  mode->hdisplay);
 }
 
-static void rcar_du_crtc_set_routing(struct rcar_du_crtc *rcrtc)
-{
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
-       u32 dorcr = rcar_du_read(rcdu, DORCR);
-
-       dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK);
-
-       /* Set the DU1 pins sources. Select CRTC 0 if explicitly requested and
-        * CRTC 1 in all other cases to avoid cloning CRTC 0 to DU0 and DU1 by
-        * default.
-        */
-       if (rcrtc->outputs & (1 << 1) && rcrtc->index == 0)
-               dorcr |= DORCR_PG2D_DS1;
-       else
-               dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2;
-
-       rcar_du_write(rcdu, DORCR, dorcr);
-}
-
-static void __rcar_du_start_stop(struct rcar_du_device *rcdu, bool start)
-{
-       rcar_du_write(rcdu, DSYSR,
-                     (rcar_du_read(rcdu, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) |
-                     (start ? DSYSR_DEN : DSYSR_DRES));
-}
-
-static void rcar_du_start_stop(struct rcar_du_device *rcdu, bool start)
-{
-       /* Many of the configuration bits are only updated when the display
-        * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some
-        * of those bits could be pre-configured, but others (especially the
-        * bits related to plane assignment to display timing controllers) need
-        * to be modified at runtime.
-        *
-        * Restart the display controller if a start is requested. Sorry for the
-        * flicker. It should be possible to move most of the "DRES-update" bits
-        * setup to driver initialization time and minimize the number of cases
-        * when the display controller will have to be restarted.
-        */
-       if (start) {
-               if (rcdu->used_crtcs++ != 0)
-                       __rcar_du_start_stop(rcdu, false);
-               __rcar_du_start_stop(rcdu, true);
-       } else {
-               if (--rcdu->used_crtcs == 0)
-                       __rcar_du_start_stop(rcdu, false);
-       }
-}
-
-void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output)
+void rcar_du_crtc_route_output(struct drm_crtc *crtc,
+                              enum rcar_du_output output)
 {
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
 
        /* Store the route from the CRTC output to the DU output. The DU will be
         * configured when starting the CRTC.
         */
-       rcrtc->outputs |= 1 << output;
+       rcrtc->outputs |= BIT(output);
+
+       /* Store RGB routing to DPAD0 for R8A7790. */
+       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_DEFR8) &&
+           output == RCAR_DU_OUTPUT_DPAD0)
+               rcdu->dpad0_source = rcrtc->index;
 }
 
 void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
 {
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
        struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
        unsigned int num_planes = 0;
@@ -182,8 +154,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
        u32 dptsr = 0;
        u32 dspr = 0;
 
-       for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
-               struct rcar_du_plane *plane = &rcdu->planes.planes[i];
+       for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
+               struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
                unsigned int j;
 
                if (plane->crtc != &rcrtc->crtc || !plane->enabled)
@@ -220,8 +192,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
        /* Select display timing and dot clock generator 2 for planes associated
         * with superposition controller 2.
         */
-       if (rcrtc->index) {
-               u32 value = rcar_du_read(rcdu, DPTSR);
+       if (rcrtc->index % 2) {
+               u32 value = rcar_du_group_read(rcrtc->group, DPTSR);
 
                /* The DPTSR register is updated when the display controller is
                 * stopped. We thus need to restart the DU. Once again, sorry
@@ -231,21 +203,19 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
                 * occur only if we need to break the pre-association.
                 */
                if (value != dptsr) {
-                       rcar_du_write(rcdu, DPTSR, dptsr);
-                       if (rcdu->used_crtcs) {
-                               __rcar_du_start_stop(rcdu, false);
-                               __rcar_du_start_stop(rcdu, true);
-                       }
+                       rcar_du_group_write(rcrtc->group, DPTSR, dptsr);
+                       if (rcrtc->group->used_crtcs)
+                               rcar_du_group_restart(rcrtc->group);
                }
        }
 
-       rcar_du_write(rcdu, rcrtc->index ? DS2PR : DS1PR, dspr);
+       rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
+                           dspr);
 }
 
 static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 {
        struct drm_crtc *crtc = &rcrtc->crtc;
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
        unsigned int i;
 
        if (rcrtc->started)
@@ -260,16 +230,16 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 
        /* Configure display timings and output routing */
        rcar_du_crtc_set_display_timing(rcrtc);
-       rcar_du_crtc_set_routing(rcrtc);
+       rcar_du_group_set_routing(rcrtc->group);
 
-       mutex_lock(&rcdu->planes.lock);
+       mutex_lock(&rcrtc->group->planes.lock);
        rcrtc->plane->enabled = true;
        rcar_du_crtc_update_planes(crtc);
-       mutex_unlock(&rcdu->planes.lock);
+       mutex_unlock(&rcrtc->group->planes.lock);
 
        /* Setup planes. */
-       for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
-               struct rcar_du_plane *plane = &rcdu->planes.planes[i];
+       for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
+               struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
 
                if (plane->crtc != crtc || !plane->enabled)
                        continue;
@@ -283,7 +253,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
         */
        rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER);
 
-       rcar_du_start_stop(rcdu, true);
+       rcar_du_group_start_stop(rcrtc->group, true);
 
        rcrtc->started = true;
 }
@@ -291,42 +261,37 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 {
        struct drm_crtc *crtc = &rcrtc->crtc;
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
 
        if (!rcrtc->started)
                return;
 
-       mutex_lock(&rcdu->planes.lock);
+       mutex_lock(&rcrtc->group->planes.lock);
        rcrtc->plane->enabled = false;
        rcar_du_crtc_update_planes(crtc);
-       mutex_unlock(&rcdu->planes.lock);
+       mutex_unlock(&rcrtc->group->planes.lock);
 
        /* Select switch sync mode. This stops display operation and configures
         * the HSYNC and VSYNC signals as inputs.
         */
        rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
 
-       rcar_du_start_stop(rcdu, false);
+       rcar_du_group_start_stop(rcrtc->group, false);
 
        rcrtc->started = false;
 }
 
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
-
        rcar_du_crtc_stop(rcrtc);
-       rcar_du_put(rcdu);
+       rcar_du_crtc_put(rcrtc);
 }
 
 void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
 {
-       struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
-
        if (rcrtc->dpms != DRM_MODE_DPMS_ON)
                return;
 
-       rcar_du_get(rcdu);
+       rcar_du_crtc_get(rcrtc);
        rcar_du_crtc_start(rcrtc);
 }
 
@@ -340,18 +305,17 @@ static void rcar_du_crtc_update_base(struct rcar_du_crtc *rcrtc)
 
 static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
        if (rcrtc->dpms == mode)
                return;
 
        if (mode == DRM_MODE_DPMS_ON) {
-               rcar_du_get(rcdu);
+               rcar_du_crtc_get(rcrtc);
                rcar_du_crtc_start(rcrtc);
        } else {
                rcar_du_crtc_stop(rcrtc);
-               rcar_du_put(rcdu);
+               rcar_du_crtc_put(rcrtc);
        }
 
        rcrtc->dpms = mode;
@@ -367,13 +331,12 @@ static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
 
 static void rcar_du_crtc_mode_prepare(struct drm_crtc *crtc)
 {
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
        /* We need to access the hardware during mode set, acquire a reference
-        * to the DU.
+        * to the CRTC.
         */
-       rcar_du_get(rcdu);
+       rcar_du_crtc_get(rcrtc);
 
        /* Stop the CRTC and release the plane. Force the DPMS mode to off as a
         * result.
@@ -390,8 +353,8 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
                                 int x, int y,
                                 struct drm_framebuffer *old_fb)
 {
-       struct rcar_du_device *rcdu = crtc->dev->dev_private;
        struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+       struct rcar_du_device *rcdu = rcrtc->group->dev;
        const struct rcar_du_format_info *format;
        int ret;
 
@@ -423,10 +386,10 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
 
 error:
        /* There's no rollback/abort operation to clean up in case of error. We
-        * thus need to release the reference to the DU acquired in prepare()
+        * thus need to release the reference to the CRTC acquired in prepare()
         * here.
         */
-       rcar_du_put(rcdu);
+       rcar_du_crtc_put(rcrtc);
        return ret;
 }
 
@@ -514,6 +477,24 @@ static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
        drm_vblank_put(dev, rcrtc->index);
 }
 
+static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
+{
+       struct rcar_du_crtc *rcrtc = arg;
+       irqreturn_t ret = IRQ_NONE;
+       u32 status;
+
+       status = rcar_du_crtc_read(rcrtc, DSSR);
+       rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
+
+       if (status & DSSR_VBK) {
+               drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index);
+               rcar_du_crtc_finish_page_flip(rcrtc);
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
 static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,
                                  struct drm_framebuffer *fb,
                                  struct drm_pending_vblank_event *event)
@@ -549,16 +530,41 @@ static const struct drm_crtc_funcs crtc_funcs = {
        .page_flip = rcar_du_crtc_page_flip,
 };
 
-int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index)
+int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 {
+       static const unsigned int mmio_offsets[] = {
+               DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET
+       };
+
+       struct rcar_du_device *rcdu = rgrp->dev;
+       struct platform_device *pdev = to_platform_device(rcdu->dev);
        struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
        struct drm_crtc *crtc = &rcrtc->crtc;
+       unsigned int irqflags;
+       char clk_name[5];
+       char *name;
+       int irq;
        int ret;
 
-       rcrtc->mmio_offset = index ? DISP2_REG_OFFSET : 0;
+       /* Get the CRTC clock. */
+       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
+               sprintf(clk_name, "du.%u", index);
+               name = clk_name;
+       } else {
+               name = NULL;
+       }
+
+       rcrtc->clock = devm_clk_get(rcdu->dev, name);
+       if (IS_ERR(rcrtc->clock)) {
+               dev_err(rcdu->dev, "no clock for CRTC %u\n", index);
+               return PTR_ERR(rcrtc->clock);
+       }
+
+       rcrtc->group = rgrp;
+       rcrtc->mmio_offset = mmio_offsets[index];
        rcrtc->index = index;
        rcrtc->dpms = DRM_MODE_DPMS_OFF;
-       rcrtc->plane = &rcdu->planes.planes[index];
+       rcrtc->plane = &rgrp->planes.planes[index % 2];
 
        rcrtc->plane->crtc = crtc;
 
@@ -568,6 +574,28 @@ int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index)
 
        drm_crtc_helper_add(crtc, &crtc_helper_funcs);
 
+       /* Register the interrupt handler. */
+       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) {
+               irq = platform_get_irq(pdev, index);
+               irqflags = 0;
+       } else {
+               irq = platform_get_irq(pdev, 0);
+               irqflags = IRQF_SHARED;
+       }
+
+       if (irq < 0) {
+               dev_err(rcdu->dev, "no IRQ for CRTC %u\n", index);
+               return ret;
+       }
+
+       ret = devm_request_irq(rcdu->dev, irq, rcar_du_crtc_irq, irqflags,
+                              dev_name(rcdu->dev), rcrtc);
+       if (ret < 0) {
+               dev_err(rcdu->dev,
+                       "failed to register IRQ for CRTC %u\n", index);
+               return ret;
+       }
+
        return 0;
 }
 
@@ -580,16 +608,3 @@ void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable)
                rcar_du_crtc_clr(rcrtc, DIER, DIER_VBE);
        }
 }
-
-void rcar_du_crtc_irq(struct rcar_du_crtc *rcrtc)
-{
-       u32 status;
-
-       status = rcar_du_crtc_read(rcrtc, DSSR);
-       rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
-
-       if (status & DSSR_VBK) {
-               drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index);
-               rcar_du_crtc_finish_page_flip(rcrtc);
-       }
-}
index 2a0365bcbd14c481bb19542ba9b577ebe20b9553..43e7575c700c26354d9971ea211ef84a4db2cfc9 100644 (file)
 #define __RCAR_DU_CRTC_H__
 
 #include <linux/mutex.h>
+#include <linux/platform_data/rcar-du.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 
-struct rcar_du_device;
+struct rcar_du_group;
 struct rcar_du_plane;
 
 struct rcar_du_crtc {
        struct drm_crtc crtc;
 
+       struct clk *clock;
        unsigned int mmio_offset;
        unsigned int index;
        bool started;
@@ -33,18 +35,21 @@ struct rcar_du_crtc {
        unsigned int outputs;
        int dpms;
 
+       struct rcar_du_group *group;
        struct rcar_du_plane *plane;
 };
 
-int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index);
+#define to_rcar_crtc(c)        container_of(c, struct rcar_du_crtc, crtc)
+
+int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index);
 void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable);
-void rcar_du_crtc_irq(struct rcar_du_crtc *rcrtc);
 void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
                                   struct drm_file *file);
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
 void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
 
-void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output);
+void rcar_du_crtc_route_output(struct drm_crtc *crtc,
+                              enum rcar_du_output output);
 void rcar_du_crtc_update_planes(struct drm_crtc *crtc);
 
 #endif /* __RCAR_DU_CRTC_H__ */
index 5069d9c234bb71a5d9d59bcd63184f2c17240aa0..0a9f1bb88337f614a24468970a09b6024415d359 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
 #include "rcar_du_crtc.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_regs.h"
 
-/* -----------------------------------------------------------------------------
- * Core device operations
- */
-
-/*
- * rcar_du_get - Acquire a reference to the DU
- *
- * Acquiring a reference enables the device clock and setup core registers. A
- * reference must be held before accessing any hardware registers.
- *
- * This function must be called with the DRM mode_config lock held.
- *
- * Return 0 in case of success or a negative error code otherwise.
- */
-int rcar_du_get(struct rcar_du_device *rcdu)
-{
-       int ret;
-
-       if (rcdu->use_count)
-               goto done;
-
-       /* Enable clocks before accessing the hardware. */
-       ret = clk_prepare_enable(rcdu->clock);
-       if (ret < 0)
-               return ret;
-
-       /* Enable extended features */
-       rcar_du_write(rcdu, DEFR, DEFR_CODE | DEFR_DEFE);
-       rcar_du_write(rcdu, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
-       rcar_du_write(rcdu, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
-       rcar_du_write(rcdu, DEFR4, DEFR4_CODE);
-       rcar_du_write(rcdu, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
-
-       /* Use DS1PR and DS2PR to configure planes priorities and connects the
-        * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
-        */
-       rcar_du_write(rcdu, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS);
-
-done:
-       rcdu->use_count++;
-       return 0;
-}
-
-/*
- * rcar_du_put - Release a reference to the DU
- *
- * Releasing the last reference disables the device clock.
- *
- * This function must be called with the DRM mode_config lock held.
- */
-void rcar_du_put(struct rcar_du_device *rcdu)
-{
-       if (--rcdu->use_count)
-               return;
-
-       clk_disable_unprepare(rcdu->clock);
-}
-
 /* -----------------------------------------------------------------------------
  * DRM operations
  */
 
 static int rcar_du_unload(struct drm_device *dev)
 {
+       struct rcar_du_device *rcdu = dev->dev_private;
+
+       if (rcdu->fbdev)
+               drm_fbdev_cma_fini(rcdu->fbdev);
+
        drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
        drm_vblank_cleanup(dev);
-       drm_irq_uninstall(dev);
 
+       dev->irq_enabled = 0;
        dev->dev_private = NULL;
 
        return 0;
@@ -107,7 +55,6 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
        struct platform_device *pdev = dev->platformdev;
        struct rcar_du_platform_data *pdata = pdev->dev.platform_data;
        struct rcar_du_device *rcdu;
-       struct resource *ioarea;
        struct resource *mem;
        int ret;
 
@@ -124,35 +71,15 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
 
        rcdu->dev = &pdev->dev;
        rcdu->pdata = pdata;
+       rcdu->info = (struct rcar_du_device_info *)pdev->id_entry->driver_data;
        rcdu->ddev = dev;
        dev->dev_private = rcdu;
 
-       /* I/O resources and clocks */
+       /* I/O resources */
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (mem == NULL) {
-               dev_err(&pdev->dev, "failed to get memory resource\n");
-               return -EINVAL;
-       }
-
-       ioarea = devm_request_mem_region(&pdev->dev, mem->start,
-                                        resource_size(mem), pdev->name);
-       if (ioarea == NULL) {
-               dev_err(&pdev->dev, "failed to request memory region\n");
-               return -EBUSY;
-       }
-
-       rcdu->mmio = devm_ioremap_nocache(&pdev->dev, ioarea->start,
-                                         resource_size(ioarea));
-       if (rcdu->mmio == NULL) {
-               dev_err(&pdev->dev, "failed to remap memory resource\n");
-               return -ENOMEM;
-       }
-
-       rcdu->clock = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(rcdu->clock)) {
-               dev_err(&pdev->dev, "failed to get clock\n");
-               return -ENOENT;
-       }
+       rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(rcdu->mmio))
+               return PTR_ERR(rcdu->mmio);
 
        /* DRM/KMS objects */
        ret = rcar_du_modeset_init(rcdu);
@@ -161,18 +88,14 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
                goto done;
        }
 
-       /* IRQ and vblank handling */
+       /* vblank handling */
        ret = drm_vblank_init(dev, (1 << rcdu->num_crtcs) - 1);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to initialize vblank\n");
                goto done;
        }
 
-       ret = drm_irq_install(dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to install IRQ handler\n");
-               goto done;
-       }
+       dev->irq_enabled = 1;
 
        platform_set_drvdata(pdev, rcdu);
 
@@ -188,20 +111,15 @@ static void rcar_du_preclose(struct drm_device *dev, struct drm_file *file)
        struct rcar_du_device *rcdu = dev->dev_private;
        unsigned int i;
 
-       for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i)
+       for (i = 0; i < rcdu->num_crtcs; ++i)
                rcar_du_crtc_cancel_page_flip(&rcdu->crtcs[i], file);
 }
 
-static irqreturn_t rcar_du_irq(int irq, void *arg)
+static void rcar_du_lastclose(struct drm_device *dev)
 {
-       struct drm_device *dev = arg;
        struct rcar_du_device *rcdu = dev->dev_private;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i)
-               rcar_du_crtc_irq(&rcdu->crtcs[i]);
 
-       return IRQ_HANDLED;
+       drm_fbdev_cma_restore_mode(rcdu->fbdev);
 }
 
 static int rcar_du_enable_vblank(struct drm_device *dev, int crtc)
@@ -236,12 +154,11 @@ static const struct file_operations rcar_du_fops = {
 };
 
 static struct drm_driver rcar_du_driver = {
-       .driver_features        = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
-                               | DRIVER_PRIME,
+       .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME,
        .load                   = rcar_du_load,
        .unload                 = rcar_du_unload,
        .preclose               = rcar_du_preclose,
-       .irq_handler            = rcar_du_irq,
+       .lastclose              = rcar_du_lastclose,
        .get_vblank_counter     = drm_vblank_count,
        .enable_vblank          = rcar_du_enable_vblank,
        .disable_vblank         = rcar_du_disable_vblank,
@@ -313,6 +230,57 @@ static int rcar_du_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct rcar_du_device_info rcar_du_r8a7779_info = {
+       .features = 0,
+       .num_crtcs = 2,
+       .routes = {
+               /* R8A7779 has two RGB outputs and one (currently unsupported)
+                * TCON output.
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(0),
+                       .encoder_type = DRM_MODE_ENCODER_NONE,
+               },
+               [RCAR_DU_OUTPUT_DPAD1] = {
+                       .possible_crtcs = BIT(1) | BIT(0),
+                       .encoder_type = DRM_MODE_ENCODER_NONE,
+               },
+       },
+       .num_lvds = 0,
+};
+
+static const struct rcar_du_device_info rcar_du_r8a7790_info = {
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B
+                 | RCAR_DU_FEATURE_DEFR8,
+       .num_crtcs = 3,
+       .routes = {
+               /* R8A7790 has one RGB output, two LVDS outputs and one
+                * (currently unsupported) TCON output.
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
+                       .encoder_type = DRM_MODE_ENCODER_NONE,
+               },
+               [RCAR_DU_OUTPUT_LVDS0] = {
+                       .possible_crtcs = BIT(0),
+                       .encoder_type = DRM_MODE_ENCODER_LVDS,
+               },
+               [RCAR_DU_OUTPUT_LVDS1] = {
+                       .possible_crtcs = BIT(2) | BIT(1),
+                       .encoder_type = DRM_MODE_ENCODER_LVDS,
+               },
+       },
+       .num_lvds = 2,
+};
+
+static const struct platform_device_id rcar_du_id_table[] = {
+       { "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
+       { "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
+       { }
+};
+
+MODULE_DEVICE_TABLE(platform, rcar_du_id_table);
+
 static struct platform_driver rcar_du_platform_driver = {
        .probe          = rcar_du_probe,
        .remove         = rcar_du_remove,
@@ -321,6 +289,7 @@ static struct platform_driver rcar_du_platform_driver = {
                .name   = "rcar-du",
                .pm     = &rcar_du_pm_ops,
        },
+       .id_table       = rcar_du_id_table,
 };
 
 module_platform_driver(rcar_du_platform_driver);
index 193cc59d495cbd8e1a5427fae9fd1acce229dc15..65d2d636b002d9fbf32fb2c6391b8df4bc63ff03 100644 (file)
 #define __RCAR_DU_DRV_H__
 
 #include <linux/kernel.h>
-#include <linux/mutex.h>
 #include <linux/platform_data/rcar-du.h>
 
 #include "rcar_du_crtc.h"
-#include "rcar_du_plane.h"
+#include "rcar_du_group.h"
 
 struct clk;
 struct device;
 struct drm_device;
+struct drm_fbdev_cma;
+struct rcar_du_device;
+struct rcar_du_lvdsenc;
+
+#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0)        /* Per-CRTC IRQ and clock */
+#define RCAR_DU_FEATURE_ALIGN_128B     (1 << 1)        /* Align pitches to 128 bytes */
+#define RCAR_DU_FEATURE_DEFR8          (1 << 2)        /* Has DEFR8 register */
+
+/*
+ * struct rcar_du_output_routing - Output routing specification
+ * @possible_crtcs: bitmask of possible CRTCs for the output
+ * @encoder_type: DRM type of the internal encoder associated with the output
+ *
+ * The DU has 5 possible outputs (DPAD0/1, LVDS0/1, TCON). Output routing data
+ * specify the valid SoC outputs, which CRTCs can drive the output, and the type
+ * of in-SoC encoder for the output.
+ */
+struct rcar_du_output_routing {
+       unsigned int possible_crtcs;
+       unsigned int encoder_type;
+};
+
+/*
+ * struct rcar_du_device_info - DU model-specific information
+ * @features: device features (RCAR_DU_FEATURE_*)
+ * @num_crtcs: total number of CRTCs
+ * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
+ * @num_lvds: number of internal LVDS encoders
+ */
+struct rcar_du_device_info {
+       unsigned int features;
+       unsigned int num_crtcs;
+       struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
+       unsigned int num_lvds;
+};
 
 struct rcar_du_device {
        struct device *dev;
        const struct rcar_du_platform_data *pdata;
+       const struct rcar_du_device_info *info;
 
        void __iomem *mmio;
-       struct clk *clock;
-       unsigned int use_count;
 
        struct drm_device *ddev;
+       struct drm_fbdev_cma *fbdev;
 
-       struct rcar_du_crtc crtcs[2];
-       unsigned int used_crtcs;
+       struct rcar_du_crtc crtcs[3];
        unsigned int num_crtcs;
 
-       struct {
-               struct rcar_du_plane planes[RCAR_DU_NUM_SW_PLANES];
-               unsigned int free;
-               struct mutex lock;
+       struct rcar_du_group groups[2];
 
-               struct drm_property *alpha;
-               struct drm_property *colorkey;
-               struct drm_property *zpos;
-       } planes;
+       unsigned int dpad0_source;
+       struct rcar_du_lvdsenc *lvds[2];
 };
 
-int rcar_du_get(struct rcar_du_device *rcdu);
-void rcar_du_put(struct rcar_du_device *rcdu);
+static inline bool rcar_du_has(struct rcar_du_device *rcdu,
+                              unsigned int feature)
+{
+       return rcdu->info->features & feature;
+}
 
 static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
 {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
new file mode 100644 (file)
index 0000000..3daa7a1
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * rcar_du_encoder.c  --  R-Car Display Unit Encoder
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/export.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
+#include "rcar_du_kms.h"
+#include "rcar_du_lvdscon.h"
+#include "rcar_du_lvdsenc.h"
+#include "rcar_du_vgacon.h"
+
+/* -----------------------------------------------------------------------------
+ * Common connector functions
+ */
+
+struct drm_encoder *
+rcar_du_connector_best_encoder(struct drm_connector *connector)
+{
+       struct rcar_du_connector *rcon = to_rcar_connector(connector);
+
+       return &rcon->encoder->encoder;
+}
+
+/* -----------------------------------------------------------------------------
+ * Encoder
+ */
+
+static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+       if (renc->lvds)
+               rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc, mode);
+}
+
+static bool rcar_du_encoder_mode_fixup(struct drm_encoder *encoder,
+                                      const struct drm_display_mode *mode,
+                                      struct drm_display_mode *adjusted_mode)
+{
+       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+       const struct drm_display_mode *panel_mode;
+       struct drm_device *dev = encoder->dev;
+       struct drm_connector *connector;
+       bool found = false;
+
+       /* DAC encoders have currently no restriction on the mode. */
+       if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
+               return true;
+
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               if (connector->encoder == encoder) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found) {
+               dev_dbg(dev->dev, "mode_fixup: no connector found\n");
+               return false;
+       }
+
+       if (list_empty(&connector->modes)) {
+               dev_dbg(dev->dev, "mode_fixup: empty modes list\n");
+               return false;
+       }
+
+       panel_mode = list_first_entry(&connector->modes,
+                                     struct drm_display_mode, head);
+
+       /* We're not allowed to modify the resolution. */
+       if (mode->hdisplay != panel_mode->hdisplay ||
+           mode->vdisplay != panel_mode->vdisplay)
+               return false;
+
+       /* The flat panel mode is fixed, just copy it to the adjusted mode. */
+       drm_mode_copy(adjusted_mode, panel_mode);
+
+       /* The internal LVDS encoder has a clock frequency operating range of
+        * 30MHz to 150MHz. Clamp the clock accordingly.
+        */
+       if (renc->lvds)
+               adjusted_mode->clock = clamp(adjusted_mode->clock,
+                                            30000, 150000);
+
+       return true;
+}
+
+static void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder)
+{
+       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+       if (renc->lvds)
+               rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc,
+                                    DRM_MODE_DPMS_OFF);
+}
+
+static void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
+{
+       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+       if (renc->lvds)
+               rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc,
+                                    DRM_MODE_DPMS_ON);
+}
+
+static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
+                                    struct drm_display_mode *mode,
+                                    struct drm_display_mode *adjusted_mode)
+{
+       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+       rcar_du_crtc_route_output(encoder->crtc, renc->output);
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+       .dpms = rcar_du_encoder_dpms,
+       .mode_fixup = rcar_du_encoder_mode_fixup,
+       .prepare = rcar_du_encoder_mode_prepare,
+       .commit = rcar_du_encoder_mode_commit,
+       .mode_set = rcar_du_encoder_mode_set,
+};
+
+static const struct drm_encoder_funcs encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+int rcar_du_encoder_init(struct rcar_du_device *rcdu,
+                        enum rcar_du_encoder_type type,
+                        enum rcar_du_output output,
+                        const struct rcar_du_encoder_data *data)
+{
+       struct rcar_du_encoder *renc;
+       unsigned int encoder_type;
+       int ret;
+
+       renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
+       if (renc == NULL)
+               return -ENOMEM;
+
+       renc->output = output;
+
+       switch (output) {
+       case RCAR_DU_OUTPUT_LVDS0:
+               renc->lvds = rcdu->lvds[0];
+               break;
+
+       case RCAR_DU_OUTPUT_LVDS1:
+               renc->lvds = rcdu->lvds[1];
+               break;
+
+       default:
+               break;
+       }
+
+       switch (type) {
+       case RCAR_DU_ENCODER_VGA:
+               encoder_type = DRM_MODE_ENCODER_DAC;
+               break;
+       case RCAR_DU_ENCODER_LVDS:
+               encoder_type = DRM_MODE_ENCODER_LVDS;
+               break;
+       case RCAR_DU_ENCODER_NONE:
+       default:
+               /* No external encoder, use the internal encoder type. */
+               encoder_type = rcdu->info->routes[output].encoder_type;
+               break;
+       }
+
+       ret = drm_encoder_init(rcdu->ddev, &renc->encoder, &encoder_funcs,
+                              encoder_type);
+       if (ret < 0)
+               return ret;
+
+       drm_encoder_helper_add(&renc->encoder, &encoder_helper_funcs);
+
+       switch (encoder_type) {
+       case DRM_MODE_ENCODER_LVDS:
+               return rcar_du_lvds_connector_init(rcdu, renc,
+                                                  &data->connector.lvds.panel);
+
+       case DRM_MODE_ENCODER_DAC:
+               return rcar_du_vga_connector_init(rcdu, renc);
+
+       default:
+               return -EINVAL;
+       }
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
new file mode 100644 (file)
index 0000000..0e5a65e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * rcar_du_encoder.h  --  R-Car Display Unit Encoder
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_ENCODER_H__
+#define __RCAR_DU_ENCODER_H__
+
+#include <linux/platform_data/rcar-du.h>
+
+#include <drm/drm_crtc.h>
+
+struct rcar_du_device;
+struct rcar_du_lvdsenc;
+
+struct rcar_du_encoder {
+       struct drm_encoder encoder;
+       enum rcar_du_output output;
+       struct rcar_du_lvdsenc *lvds;
+};
+
+#define to_rcar_encoder(e) \
+       container_of(e, struct rcar_du_encoder, encoder)
+
+struct rcar_du_connector {
+       struct drm_connector connector;
+       struct rcar_du_encoder *encoder;
+};
+
+#define to_rcar_connector(c) \
+       container_of(c, struct rcar_du_connector, connector)
+
+struct drm_encoder *
+rcar_du_connector_best_encoder(struct drm_connector *connector);
+
+int rcar_du_encoder_init(struct rcar_du_device *rcdu,
+                        enum rcar_du_encoder_type type,
+                        enum rcar_du_output output,
+                        const struct rcar_du_encoder_data *data);
+
+#endif /* __RCAR_DU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
new file mode 100644 (file)
index 0000000..eb53cd9
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * rcar_du_group.c  --  R-Car Display Unit Channels Pair
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+ * The R8A7779 DU is split in per-CRTC resources (scan-out engine, blending
+ * unit, timings generator, ...) and device-global resources (start/stop
+ * control, planes, ...) shared between the two CRTCs.
+ *
+ * The R8A7790 introduced a third CRTC with its own set of global resources.
+ * This would be modeled as two separate DU device instances if it wasn't for
+ * a handful or resources that are shared between the three CRTCs (mostly
+ * related to input and output routing). For this reason the R8A7790 DU must be
+ * modeled as a single device with three CRTCs, two sets of "semi-global"
+ * resources, and a few device-global resources.
+ *
+ * The rcar_du_group object is a driver specific object, without any real
+ * counterpart in the DU documentation, that models those semi-global resources.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_group.h"
+#include "rcar_du_regs.h"
+
+u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg)
+{
+       return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg);
+}
+
+void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
+{
+       rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data);
+}
+
+static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
+{
+       u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
+
+       if (!rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_DEFR8))
+               return;
+
+       /* The DEFR8 register for the first group also controls RGB output
+        * routing to DPAD0
+        */
+       if (rgrp->index == 0)
+               defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+
+       rcar_du_group_write(rgrp, DEFR8, defr8);
+}
+
+static void rcar_du_group_setup(struct rcar_du_group *rgrp)
+{
+       /* Enable extended features */
+       rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
+       rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
+       rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
+       rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+       rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
+
+       rcar_du_group_setup_defr8(rgrp);
+
+       /* Use DS1PR and DS2PR to configure planes priorities and connects the
+        * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
+        */
+       rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS);
+}
+
+/*
+ * rcar_du_group_get - Acquire a reference to the DU channels group
+ *
+ * Acquiring the first reference setups core registers. A reference must be held
+ * before accessing any hardware registers.
+ *
+ * This function must be called with the DRM mode_config lock held.
+ *
+ * Return 0 in case of success or a negative error code otherwise.
+ */
+int rcar_du_group_get(struct rcar_du_group *rgrp)
+{
+       if (rgrp->use_count)
+               goto done;
+
+       rcar_du_group_setup(rgrp);
+
+done:
+       rgrp->use_count++;
+       return 0;
+}
+
+/*
+ * rcar_du_group_put - Release a reference to the DU
+ *
+ * This function must be called with the DRM mode_config lock held.
+ */
+void rcar_du_group_put(struct rcar_du_group *rgrp)
+{
+       --rgrp->use_count;
+}
+
+static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
+{
+       rcar_du_group_write(rgrp, DSYSR,
+               (rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) |
+               (start ? DSYSR_DEN : DSYSR_DRES));
+}
+
+void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
+{
+       /* Many of the configuration bits are only updated when the display
+        * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some
+        * of those bits could be pre-configured, but others (especially the
+        * bits related to plane assignment to display timing controllers) need
+        * to be modified at runtime.
+        *
+        * Restart the display controller if a start is requested. Sorry for the
+        * flicker. It should be possible to move most of the "DRES-update" bits
+        * setup to driver initialization time and minimize the number of cases
+        * when the display controller will have to be restarted.
+        */
+       if (start) {
+               if (rgrp->used_crtcs++ != 0)
+                       __rcar_du_group_start_stop(rgrp, false);
+               __rcar_du_group_start_stop(rgrp, true);
+       } else {
+               if (--rgrp->used_crtcs == 0)
+                       __rcar_du_group_start_stop(rgrp, false);
+       }
+}
+
+void rcar_du_group_restart(struct rcar_du_group *rgrp)
+{
+       __rcar_du_group_start_stop(rgrp, false);
+       __rcar_du_group_start_stop(rgrp, true);
+}
+
+static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
+{
+       int ret;
+
+       /* RGB output routing to DPAD0 is configured in the DEFR8 register of
+        * the first group. As this function can be called with the DU0 and DU1
+        * CRTCs disabled, we need to enable the first group clock before
+        * accessing the register.
+        */
+       ret = clk_prepare_enable(rcdu->crtcs[0].clock);
+       if (ret < 0)
+               return ret;
+
+       rcar_du_group_setup_defr8(&rcdu->groups[0]);
+
+       clk_disable_unprepare(rcdu->crtcs[0].clock);
+
+       return 0;
+}
+
+int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
+{
+       struct rcar_du_crtc *crtc0 = &rgrp->dev->crtcs[rgrp->index * 2];
+       u32 dorcr = rcar_du_group_read(rgrp, DORCR);
+
+       dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK);
+
+       /* Set the DPAD1 pins sources. Select CRTC 0 if explicitly requested and
+        * CRTC 1 in all other cases to avoid cloning CRTC 0 to DPAD0 and DPAD1
+        * by default.
+        */
+       if (crtc0->outputs & BIT(RCAR_DU_OUTPUT_DPAD1))
+               dorcr |= DORCR_PG2D_DS1;
+       else
+               dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2;
+
+       rcar_du_group_write(rgrp, DORCR, dorcr);
+
+       return rcar_du_set_dpad0_routing(rgrp->dev);
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
new file mode 100644 (file)
index 0000000..5025930
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * rcar_du_group.c  --  R-Car Display Unit Planes and CRTCs Group
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_GROUP_H__
+#define __RCAR_DU_GROUP_H__
+
+#include "rcar_du_plane.h"
+
+struct rcar_du_device;
+
+/*
+ * struct rcar_du_group - CRTCs and planes group
+ * @dev: the DU device
+ * @mmio_offset: registers offset in the device memory map
+ * @index: group index
+ * @use_count: number of users of the group (rcar_du_group_(get|put))
+ * @used_crtcs: number of CRTCs currently in use
+ * @planes: planes handled by the group
+ */
+struct rcar_du_group {
+       struct rcar_du_device *dev;
+       unsigned int mmio_offset;
+       unsigned int index;
+
+       unsigned int use_count;
+       unsigned int used_crtcs;
+
+       struct rcar_du_planes planes;
+};
+
+u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
+void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data);
+
+int rcar_du_group_get(struct rcar_du_group *rgrp);
+void rcar_du_group_put(struct rcar_du_group *rgrp);
+void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
+void rcar_du_group_restart(struct rcar_du_group *rgrp);
+int rcar_du_group_set_routing(struct rcar_du_group *rgrp);
+
+#endif /* __RCAR_DU_GROUP_H__ */
index d30c2e29bee2f122d8cff43681449fbe9e8ae46b..b31ac080c4a77ba6554ae281d0fd90754e8d633b 100644 (file)
 
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
 #include "rcar_du_kms.h"
-#include "rcar_du_lvds.h"
+#include "rcar_du_lvdsenc.h"
 #include "rcar_du_regs.h"
-#include "rcar_du_vga.h"
 
 /* -----------------------------------------------------------------------------
  * Format helpers
@@ -105,35 +105,6 @@ const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc)
        return NULL;
 }
 
-/* -----------------------------------------------------------------------------
- * Common connector and encoder functions
- */
-
-struct drm_encoder *
-rcar_du_connector_best_encoder(struct drm_connector *connector)
-{
-       struct rcar_du_connector *rcon = to_rcar_connector(connector);
-
-       return &rcon->encoder->encoder;
-}
-
-void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder)
-{
-}
-
-void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode)
-{
-       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
-
-       rcar_du_crtc_route_output(encoder->crtc, renc->output);
-}
-
-void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
-{
-}
-
 /* -----------------------------------------------------------------------------
  * Frame buffer
  */
@@ -141,11 +112,18 @@ void rcar_du_encoder_mode_commit(struct drm_encoder *encoder)
 int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
                        struct drm_mode_create_dumb *args)
 {
+       struct rcar_du_device *rcdu = dev->dev_private;
        unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
        unsigned int align;
 
-       /* The pitch must be aligned to a 16 pixels boundary. */
-       align = 16 * args->bpp / 8;
+       /* The R8A7779 DU requires a 16 pixels pitch alignment as documented,
+        * but the R8A7790 DU seems to require a 128 bytes pitch alignment.
+        */
+       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
+               align = 128;
+       else
+               align = 16 * args->bpp / 8;
+
        args->pitch = roundup(max(args->pitch, min_pitch), align);
 
        return drm_gem_cma_dumb_create(file, dev, args);
@@ -155,6 +133,7 @@ static struct drm_framebuffer *
 rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                  struct drm_mode_fb_cmd2 *mode_cmd)
 {
+       struct rcar_du_device *rcdu = dev->dev_private;
        const struct rcar_du_format_info *format;
        unsigned int align;
 
@@ -165,7 +144,10 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                return ERR_PTR(-EINVAL);
        }
 
-       align = 16 * format->bpp / 8;
+       if (rcar_du_has(rcdu, RCAR_DU_FEATURE_ALIGN_128B))
+               align = 128;
+       else
+               align = 16 * format->bpp / 8;
 
        if (mode_cmd->pitches[0] & (align - 1) ||
            mode_cmd->pitches[0] >= 8192) {
@@ -185,81 +167,124 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
        return drm_fb_cma_create(dev, file_priv, mode_cmd);
 }
 
+static void rcar_du_output_poll_changed(struct drm_device *dev)
+{
+       struct rcar_du_device *rcdu = dev->dev_private;
+
+       drm_fbdev_cma_hotplug_event(rcdu->fbdev);
+}
+
 static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
        .fb_create = rcar_du_fb_create,
+       .output_poll_changed = rcar_du_output_poll_changed,
 };
 
 int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 {
+       static const unsigned int mmio_offsets[] = {
+               DU0_REG_OFFSET, DU2_REG_OFFSET
+       };
+
        struct drm_device *dev = rcdu->ddev;
        struct drm_encoder *encoder;
+       struct drm_fbdev_cma *fbdev;
+       unsigned int num_groups;
        unsigned int i;
        int ret;
 
-       drm_mode_config_init(rcdu->ddev);
+       drm_mode_config_init(dev);
 
-       rcdu->ddev->mode_config.min_width = 0;
-       rcdu->ddev->mode_config.min_height = 0;
-       rcdu->ddev->mode_config.max_width = 4095;
-       rcdu->ddev->mode_config.max_height = 2047;
-       rcdu->ddev->mode_config.funcs = &rcar_du_mode_config_funcs;
+       dev->mode_config.min_width = 0;
+       dev->mode_config.min_height = 0;
+       dev->mode_config.max_width = 4095;
+       dev->mode_config.max_height = 2047;
+       dev->mode_config.funcs = &rcar_du_mode_config_funcs;
 
-       ret = rcar_du_plane_init(rcdu);
-       if (ret < 0)
-               return ret;
+       rcdu->num_crtcs = rcdu->info->num_crtcs;
+
+       /* Initialize the groups. */
+       num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
+
+       for (i = 0; i < num_groups; ++i) {
+               struct rcar_du_group *rgrp = &rcdu->groups[i];
+
+               rgrp->dev = rcdu;
+               rgrp->mmio_offset = mmio_offsets[i];
+               rgrp->index = i;
+
+               ret = rcar_du_planes_init(rgrp);
+               if (ret < 0)
+                       return ret;
+       }
+
+       /* Create the CRTCs. */
+       for (i = 0; i < rcdu->num_crtcs; ++i) {
+               struct rcar_du_group *rgrp = &rcdu->groups[i / 2];
 
-       for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i) {
-               ret = rcar_du_crtc_create(rcdu, i);
+               ret = rcar_du_crtc_create(rgrp, i);
                if (ret < 0)
                        return ret;
        }
 
-       rcdu->used_crtcs = 0;
-       rcdu->num_crtcs = i;
+       /* Initialize the encoders. */
+       ret = rcar_du_lvdsenc_init(rcdu);
+       if (ret < 0)
+               return ret;
 
        for (i = 0; i < rcdu->pdata->num_encoders; ++i) {
                const struct rcar_du_encoder_data *pdata =
                        &rcdu->pdata->encoders[i];
+               const struct rcar_du_output_routing *route =
+                       &rcdu->info->routes[pdata->output];
+
+               if (pdata->type == RCAR_DU_ENCODER_UNUSED)
+                       continue;
 
-               if (pdata->output >= ARRAY_SIZE(rcdu->crtcs)) {
+               if (pdata->output >= RCAR_DU_OUTPUT_MAX ||
+                   route->possible_crtcs == 0) {
                        dev_warn(rcdu->dev,
                                 "encoder %u references unexisting output %u, skipping\n",
                                 i, pdata->output);
                        continue;
                }
 
-               switch (pdata->encoder) {
-               case RCAR_DU_ENCODER_VGA:
-                       rcar_du_vga_init(rcdu, &pdata->u.vga, pdata->output);
-                       break;
-
-               case RCAR_DU_ENCODER_LVDS:
-                       rcar_du_lvds_init(rcdu, &pdata->u.lvds, pdata->output);
-                       break;
-
-               default:
-                       break;
-               }
+               rcar_du_encoder_init(rcdu, pdata->type, pdata->output, pdata);
        }
 
-       /* Set the possible CRTCs and possible clones. All encoders can be
-        * driven by the CRTC associated with the output they're connected to,
-        * as well as by CRTC 0.
+       /* Set the possible CRTCs and possible clones. There's always at least
+        * one way for all encoders to clone each other, set all bits in the
+        * possible clones field.
         */
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
                struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+               const struct rcar_du_output_routing *route =
+                       &rcdu->info->routes[renc->output];
 
-               encoder->possible_crtcs = (1 << 0) | (1 << renc->output);
-               encoder->possible_clones = 1 << 0;
+               encoder->possible_crtcs = route->possible_crtcs;
+               encoder->possible_clones = (1 << rcdu->pdata->num_encoders) - 1;
        }
 
-       ret = rcar_du_plane_register(rcdu);
-       if (ret < 0)
-               return ret;
+       /* Now that the CRTCs have been initialized register the planes. */
+       for (i = 0; i < num_groups; ++i) {
+               ret = rcar_du_planes_register(&rcdu->groups[i]);
+               if (ret < 0)
+                       return ret;
+       }
+
+       drm_kms_helper_poll_init(dev);
+
+       drm_helper_disable_unused_functions(dev);
+
+       fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
+                                  dev->mode_config.num_connector);
+       if (IS_ERR(fbdev))
+               return PTR_ERR(fbdev);
 
-       drm_kms_helper_poll_init(rcdu->ddev);
+#ifndef CONFIG_FRAMEBUFFER_CONSOLE
+       drm_fbdev_cma_restore_mode(fbdev);
+#endif
 
-       drm_helper_disable_unused_functions(rcdu->ddev);
+       rcdu->fbdev = fbdev;
 
        return 0;
 }
index dba472263486d9521028f4d1c265c196c1e1da47..5750e6af56557b36b4821953fced65372170fa09 100644 (file)
@@ -16,8 +16,9 @@
 
 #include <linux/types.h>
 
-#include <drm/drm_crtc.h>
-
+struct drm_file;
+struct drm_device;
+struct drm_mode_create_dumb;
 struct rcar_du_device;
 
 struct rcar_du_format_info {
@@ -28,32 +29,8 @@ struct rcar_du_format_info {
        unsigned int edf;
 };
 
-struct rcar_du_encoder {
-       struct drm_encoder encoder;
-       unsigned int output;
-};
-
-#define to_rcar_encoder(e) \
-       container_of(e, struct rcar_du_encoder, encoder)
-
-struct rcar_du_connector {
-       struct drm_connector connector;
-       struct rcar_du_encoder *encoder;
-};
-
-#define to_rcar_connector(c) \
-       container_of(c, struct rcar_du_connector, connector)
-
 const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc);
 
-struct drm_encoder *
-rcar_du_connector_best_encoder(struct drm_connector *connector);
-void rcar_du_encoder_mode_prepare(struct drm_encoder *encoder);
-void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode);
-void rcar_du_encoder_mode_commit(struct drm_encoder *encoder);
-
 int rcar_du_modeset_init(struct rcar_du_device *rcdu);
 
 int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvds.c b/drivers/gpu/drm/rcar-du/rcar_du_lvds.c
deleted file mode 100644 (file)
index 7aefe72..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * rcar_du_lvds.c  --  R-Car Display Unit LVDS Encoder and Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_lvds.h"
-
-struct rcar_du_lvds_connector {
-       struct rcar_du_connector connector;
-
-       const struct rcar_du_panel_data *panel;
-};
-
-#define to_rcar_lvds_connector(c) \
-       container_of(c, struct rcar_du_lvds_connector, connector.connector)
-
-/* -----------------------------------------------------------------------------
- * Connector
- */
-
-static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
-{
-       struct rcar_du_lvds_connector *lvdscon = to_rcar_lvds_connector(connector);
-       struct drm_display_mode *mode;
-
-       mode = drm_mode_create(connector->dev);
-       if (mode == NULL)
-               return 0;
-
-       mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
-       mode->clock = lvdscon->panel->mode.clock;
-       mode->hdisplay = lvdscon->panel->mode.hdisplay;
-       mode->hsync_start = lvdscon->panel->mode.hsync_start;
-       mode->hsync_end = lvdscon->panel->mode.hsync_end;
-       mode->htotal = lvdscon->panel->mode.htotal;
-       mode->vdisplay = lvdscon->panel->mode.vdisplay;
-       mode->vsync_start = lvdscon->panel->mode.vsync_start;
-       mode->vsync_end = lvdscon->panel->mode.vsync_end;
-       mode->vtotal = lvdscon->panel->mode.vtotal;
-       mode->flags = lvdscon->panel->mode.flags;
-
-       drm_mode_set_name(mode);
-       drm_mode_probed_add(connector, mode);
-
-       return 1;
-}
-
-static int rcar_du_lvds_connector_mode_valid(struct drm_connector *connector,
-                                           struct drm_display_mode *mode)
-{
-       return MODE_OK;
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-       .get_modes = rcar_du_lvds_connector_get_modes,
-       .mode_valid = rcar_du_lvds_connector_mode_valid,
-       .best_encoder = rcar_du_connector_best_encoder,
-};
-
-static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
-{
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-}
-
-static enum drm_connector_status
-rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
-{
-       return connector_status_connected;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .detect = rcar_du_lvds_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = rcar_du_lvds_connector_destroy,
-};
-
-static int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
-                                      struct rcar_du_encoder *renc,
-                                      const struct rcar_du_panel_data *panel)
-{
-       struct rcar_du_lvds_connector *lvdscon;
-       struct drm_connector *connector;
-       int ret;
-
-       lvdscon = devm_kzalloc(rcdu->dev, sizeof(*lvdscon), GFP_KERNEL);
-       if (lvdscon == NULL)
-               return -ENOMEM;
-
-       lvdscon->panel = panel;
-
-       connector = &lvdscon->connector.connector;
-       connector->display_info.width_mm = panel->width_mm;
-       connector->display_info.height_mm = panel->height_mm;
-
-       ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-                                DRM_MODE_CONNECTOR_LVDS);
-       if (ret < 0)
-               return ret;
-
-       drm_connector_helper_add(connector, &connector_helper_funcs);
-       ret = drm_sysfs_connector_add(connector);
-       if (ret < 0)
-               return ret;
-
-       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-       drm_object_property_set_value(&connector->base,
-               rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-       ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
-       if (ret < 0)
-               return ret;
-
-       connector->encoder = &renc->encoder;
-       lvdscon->connector.encoder = renc;
-
-       return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Encoder
- */
-
-static void rcar_du_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-}
-
-static bool rcar_du_lvds_encoder_mode_fixup(struct drm_encoder *encoder,
-                                          const struct drm_display_mode *mode,
-                                          struct drm_display_mode *adjusted_mode)
-{
-       const struct drm_display_mode *panel_mode;
-       struct drm_device *dev = encoder->dev;
-       struct drm_connector *connector;
-       bool found = false;
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (connector->encoder == encoder) {
-                       found = true;
-                       break;
-               }
-       }
-
-       if (!found) {
-               dev_dbg(dev->dev, "mode_fixup: no connector found\n");
-               return false;
-       }
-
-       if (list_empty(&connector->modes)) {
-               dev_dbg(dev->dev, "mode_fixup: empty modes list\n");
-               return false;
-       }
-
-       panel_mode = list_first_entry(&connector->modes,
-                                     struct drm_display_mode, head);
-
-       /* We're not allowed to modify the resolution. */
-       if (mode->hdisplay != panel_mode->hdisplay ||
-           mode->vdisplay != panel_mode->vdisplay)
-               return false;
-
-       /* The flat panel mode is fixed, just copy it to the adjusted mode. */
-       drm_mode_copy(adjusted_mode, panel_mode);
-
-       return true;
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-       .dpms = rcar_du_lvds_encoder_dpms,
-       .mode_fixup = rcar_du_lvds_encoder_mode_fixup,
-       .prepare = rcar_du_encoder_mode_prepare,
-       .commit = rcar_du_encoder_mode_commit,
-       .mode_set = rcar_du_encoder_mode_set,
-};
-
-static const struct drm_encoder_funcs encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-int rcar_du_lvds_init(struct rcar_du_device *rcdu,
-                     const struct rcar_du_encoder_lvds_data *data,
-                     unsigned int output)
-{
-       struct rcar_du_encoder *renc;
-       int ret;
-
-       renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
-       if (renc == NULL)
-               return -ENOMEM;
-
-       renc->output = output;
-
-       ret = drm_encoder_init(rcdu->ddev, &renc->encoder, &encoder_funcs,
-                              DRM_MODE_ENCODER_LVDS);
-       if (ret < 0)
-               return ret;
-
-       drm_encoder_helper_add(&renc->encoder, &encoder_helper_funcs);
-
-       return rcar_du_lvds_connector_init(rcdu, renc, &data->panel);
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvds.h b/drivers/gpu/drm/rcar-du/rcar_du_lvds.h
deleted file mode 100644 (file)
index b47f832..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * rcar_du_lvds.h  --  R-Car Display Unit LVDS Encoder and Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_LVDS_H__
-#define __RCAR_DU_LVDS_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder_lvds_data;
-
-int rcar_du_lvds_init(struct rcar_du_device *rcdu,
-                     const struct rcar_du_encoder_lvds_data *data,
-                     unsigned int output);
-
-#endif /* __RCAR_DU_LVDS_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
new file mode 100644 (file)
index 0000000..4f3ba93
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * rcar_du_lvdscon.c  --  R-Car Display Unit LVDS Connector
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
+#include "rcar_du_kms.h"
+#include "rcar_du_lvdscon.h"
+
+struct rcar_du_lvds_connector {
+       struct rcar_du_connector connector;
+
+       const struct rcar_du_panel_data *panel;
+};
+
+#define to_rcar_lvds_connector(c) \
+       container_of(c, struct rcar_du_lvds_connector, connector.connector)
+
+static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
+{
+       struct rcar_du_lvds_connector *lvdscon =
+               to_rcar_lvds_connector(connector);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_create(connector->dev);
+       if (mode == NULL)
+               return 0;
+
+       mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+       mode->clock = lvdscon->panel->mode.clock;
+       mode->hdisplay = lvdscon->panel->mode.hdisplay;
+       mode->hsync_start = lvdscon->panel->mode.hsync_start;
+       mode->hsync_end = lvdscon->panel->mode.hsync_end;
+       mode->htotal = lvdscon->panel->mode.htotal;
+       mode->vdisplay = lvdscon->panel->mode.vdisplay;
+       mode->vsync_start = lvdscon->panel->mode.vsync_start;
+       mode->vsync_end = lvdscon->panel->mode.vsync_end;
+       mode->vtotal = lvdscon->panel->mode.vtotal;
+       mode->flags = lvdscon->panel->mode.flags;
+
+       drm_mode_set_name(mode);
+       drm_mode_probed_add(connector, mode);
+
+       return 1;
+}
+
+static int rcar_du_lvds_connector_mode_valid(struct drm_connector *connector,
+                                           struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+       .get_modes = rcar_du_lvds_connector_get_modes,
+       .mode_valid = rcar_du_lvds_connector_mode_valid,
+       .best_encoder = rcar_du_connector_best_encoder,
+};
+
+static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
+{
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
+{
+       return connector_status_connected;
+}
+
+static const struct drm_connector_funcs connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = rcar_du_lvds_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = rcar_du_lvds_connector_destroy,
+};
+
+int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
+                               struct rcar_du_encoder *renc,
+                               const struct rcar_du_panel_data *panel)
+{
+       struct rcar_du_lvds_connector *lvdscon;
+       struct drm_connector *connector;
+       int ret;
+
+       lvdscon = devm_kzalloc(rcdu->dev, sizeof(*lvdscon), GFP_KERNEL);
+       if (lvdscon == NULL)
+               return -ENOMEM;
+
+       lvdscon->panel = panel;
+
+       connector = &lvdscon->connector.connector;
+       connector->display_info.width_mm = panel->width_mm;
+       connector->display_info.height_mm = panel->height_mm;
+
+       ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
+                                DRM_MODE_CONNECTOR_LVDS);
+       if (ret < 0)
+               return ret;
+
+       drm_connector_helper_add(connector, &connector_helper_funcs);
+       ret = drm_sysfs_connector_add(connector);
+       if (ret < 0)
+               return ret;
+
+       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+       drm_object_property_set_value(&connector->base,
+               rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+
+       ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
+       if (ret < 0)
+               return ret;
+
+       connector->encoder = &renc->encoder;
+       lvdscon->connector.encoder = renc;
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
new file mode 100644 (file)
index 0000000..bff8683
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * rcar_du_lvdscon.h  --  R-Car Display Unit LVDS Connector
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_LVDSCON_H__
+#define __RCAR_DU_LVDSCON_H__
+
+struct rcar_du_device;
+struct rcar_du_encoder;
+struct rcar_du_panel_data;
+
+int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
+                               struct rcar_du_encoder *renc,
+                               const struct rcar_du_panel_data *panel);
+
+#endif /* __RCAR_DU_LVDSCON_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
new file mode 100644 (file)
index 0000000..a0f6a17
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * rcar_du_lvdsenc.c  --  R-Car Display Unit LVDS Encoder
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
+#include "rcar_du_lvdsenc.h"
+#include "rcar_lvds_regs.h"
+
+struct rcar_du_lvdsenc {
+       struct rcar_du_device *dev;
+
+       unsigned int index;
+       void __iomem *mmio;
+       struct clk *clock;
+       int dpms;
+
+       enum rcar_lvds_input input;
+};
+
+static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
+{
+       iowrite32(data, lvds->mmio + reg);
+}
+
+static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
+                                struct rcar_du_crtc *rcrtc)
+{
+       const struct drm_display_mode *mode = &rcrtc->crtc.mode;
+       unsigned int freq = mode->clock;
+       u32 lvdcr0;
+       u32 pllcr;
+       int ret;
+
+       if (lvds->dpms == DRM_MODE_DPMS_ON)
+               return 0;
+
+       ret = clk_prepare_enable(lvds->clock);
+       if (ret < 0)
+               return ret;
+
+       /* PLL clock configuration */
+       if (freq <= 38000)
+               pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
+       else if (freq <= 60000)
+               pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
+       else if (freq <= 121000)
+               pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
+       else
+               pllcr = LVDPLLCR_PLLDLYCNT_150M;
+
+       rcar_lvds_write(lvds, LVDPLLCR, pllcr);
+
+       /* Hardcode the channels and control signals routing for now.
+        *
+        * HSYNC -> CTRL0
+        * VSYNC -> CTRL1
+        * DISP  -> CTRL2
+        * 0     -> CTRL3
+        *
+        * Channels 1 and 3 are switched on ES1.
+        */
+       rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
+                       LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
+                       LVDCTRCR_CTR0SEL_HSYNC);
+       rcar_lvds_write(lvds, LVDCHCR,
+                       LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3) |
+                       LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1));
+
+       /* Select the input, hardcode mode 0, enable LVDS operation and turn
+        * bias circuitry on.
+        */
+       lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN;
+       if (rcrtc->index == 2)
+               lvdcr0 |= LVDCR0_DUSEL;
+       rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+       /* Turn all the channels on. */
+       rcar_lvds_write(lvds, LVDCR1, LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
+                       LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
+
+       /* Turn the PLL on, wait for the startup delay, and turn the output
+        * on.
+        */
+       lvdcr0 |= LVDCR0_PLLEN;
+       rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+       usleep_range(100, 150);
+
+       lvdcr0 |= LVDCR0_LVRES;
+       rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+       lvds->dpms = DRM_MODE_DPMS_ON;
+       return 0;
+}
+
+static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds)
+{
+       if (lvds->dpms == DRM_MODE_DPMS_OFF)
+               return;
+
+       rcar_lvds_write(lvds, LVDCR0, 0);
+       rcar_lvds_write(lvds, LVDCR1, 0);
+
+       clk_disable_unprepare(lvds->clock);
+
+       lvds->dpms = DRM_MODE_DPMS_OFF;
+}
+
+int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds,
+                        struct drm_crtc *crtc, int mode)
+{
+       if (mode == DRM_MODE_DPMS_OFF) {
+               rcar_du_lvdsenc_stop(lvds);
+               return 0;
+       } else if (crtc) {
+               struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+               return rcar_du_lvdsenc_start(lvds, rcrtc);
+       } else
+               return -EINVAL;
+}
+
+static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
+                                        struct platform_device *pdev)
+{
+       struct resource *mem;
+       char name[7];
+
+       sprintf(name, "lvds.%u", lvds->index);
+
+       mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+       if (mem == NULL) {
+               dev_err(&pdev->dev, "failed to get memory resource for %s\n",
+                       name);
+               return -EINVAL;
+       }
+
+       lvds->mmio = devm_ioremap_resource(&pdev->dev, mem);
+       if (lvds->mmio == NULL) {
+               dev_err(&pdev->dev, "failed to remap memory resource for %s\n",
+                       name);
+               return -ENOMEM;
+       }
+
+       lvds->clock = devm_clk_get(&pdev->dev, name);
+       if (IS_ERR(lvds->clock)) {
+               dev_err(&pdev->dev, "failed to get clock for %s\n", name);
+               return PTR_ERR(lvds->clock);
+       }
+
+       return 0;
+}
+
+int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
+{
+       struct platform_device *pdev = to_platform_device(rcdu->dev);
+       struct rcar_du_lvdsenc *lvds;
+       unsigned int i;
+       int ret;
+
+       for (i = 0; i < rcdu->info->num_lvds; ++i) {
+               lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
+               if (lvds == NULL) {
+                       dev_err(&pdev->dev, "failed to allocate private data\n");
+                       return -ENOMEM;
+               }
+
+               lvds->dev = rcdu;
+               lvds->index = i;
+               lvds->input = i ? RCAR_LVDS_INPUT_DU1 : RCAR_LVDS_INPUT_DU0;
+               lvds->dpms = DRM_MODE_DPMS_OFF;
+
+               ret = rcar_du_lvdsenc_get_resources(lvds, pdev);
+               if (ret < 0)
+                       return ret;
+
+               rcdu->lvds[i] = lvds;
+       }
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
new file mode 100644 (file)
index 0000000..7051c6d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * rcar_du_lvdsenc.h  --  R-Car Display Unit LVDS Encoder
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_LVDSENC_H__
+#define __RCAR_DU_LVDSENC_H__
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_data/rcar-du.h>
+
+struct rcar_drm_crtc;
+struct rcar_du_lvdsenc;
+
+enum rcar_lvds_input {
+       RCAR_LVDS_INPUT_DU0,
+       RCAR_LVDS_INPUT_DU1,
+       RCAR_LVDS_INPUT_DU2,
+};
+
+#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
+int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
+int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds,
+                        struct drm_crtc *crtc, int mode);
+#else
+static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
+{
+       return 0;
+}
+static inline int rcar_du_lvdsenc_dpms(struct rcar_du_lvdsenc *lvds,
+                                      struct drm_crtc *crtc, int mode)
+{
+       return 0;
+}
+#endif
+
+#endif /* __RCAR_DU_LVDSENC_H__ */
index a65f81ddf51df67c146143ecaffa688aa5b947a6..53000644733f29c25a5db1edb5d24e5090bbc666 100644 (file)
@@ -36,90 +36,95 @@ static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
        return container_of(plane, struct rcar_du_kms_plane, plane)->hwplane;
 }
 
-static u32 rcar_du_plane_read(struct rcar_du_device *rcdu,
+static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
                              unsigned int index, u32 reg)
 {
-       return rcar_du_read(rcdu, index * PLANE_OFF + reg);
+       return rcar_du_read(rgrp->dev,
+                           rgrp->mmio_offset + index * PLANE_OFF + reg);
 }
 
-static void rcar_du_plane_write(struct rcar_du_device *rcdu,
+static void rcar_du_plane_write(struct rcar_du_group *rgrp,
                                unsigned int index, u32 reg, u32 data)
 {
-       rcar_du_write(rcdu, index * PLANE_OFF + reg, data);
+       rcar_du_write(rgrp->dev, rgrp->mmio_offset + index * PLANE_OFF + reg,
+                     data);
 }
 
 int rcar_du_plane_reserve(struct rcar_du_plane *plane,
                          const struct rcar_du_format_info *format)
 {
-       struct rcar_du_device *rcdu = plane->dev;
+       struct rcar_du_group *rgrp = plane->group;
        unsigned int i;
        int ret = -EBUSY;
 
-       mutex_lock(&rcdu->planes.lock);
+       mutex_lock(&rgrp->planes.lock);
 
-       for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
-               if (!(rcdu->planes.free & (1 << i)))
+       for (i = 0; i < ARRAY_SIZE(rgrp->planes.planes); ++i) {
+               if (!(rgrp->planes.free & (1 << i)))
                        continue;
 
                if (format->planes == 1 ||
-                   rcdu->planes.free & (1 << ((i + 1) % 8)))
+                   rgrp->planes.free & (1 << ((i + 1) % 8)))
                        break;
        }
 
-       if (i == ARRAY_SIZE(rcdu->planes.planes))
+       if (i == ARRAY_SIZE(rgrp->planes.planes))
                goto done;
 
-       rcdu->planes.free &= ~(1 << i);
+       rgrp->planes.free &= ~(1 << i);
        if (format->planes == 2)
-               rcdu->planes.free &= ~(1 << ((i + 1) % 8));
+               rgrp->planes.free &= ~(1 << ((i + 1) % 8));
 
        plane->hwindex = i;
 
        ret = 0;
 
 done:
-       mutex_unlock(&rcdu->planes.lock);
+       mutex_unlock(&rgrp->planes.lock);
        return ret;
 }
 
 void rcar_du_plane_release(struct rcar_du_plane *plane)
 {
-       struct rcar_du_device *rcdu = plane->dev;
+       struct rcar_du_group *rgrp = plane->group;
 
        if (plane->hwindex == -1)
                return;
 
-       mutex_lock(&rcdu->planes.lock);
-       rcdu->planes.free |= 1 << plane->hwindex;
+       mutex_lock(&rgrp->planes.lock);
+       rgrp->planes.free |= 1 << plane->hwindex;
        if (plane->format->planes == 2)
-               rcdu->planes.free |= 1 << ((plane->hwindex + 1) % 8);
-       mutex_unlock(&rcdu->planes.lock);
+               rgrp->planes.free |= 1 << ((plane->hwindex + 1) % 8);
+       mutex_unlock(&rgrp->planes.lock);
 
        plane->hwindex = -1;
 }
 
 void rcar_du_plane_update_base(struct rcar_du_plane *plane)
 {
-       struct rcar_du_device *rcdu = plane->dev;
+       struct rcar_du_group *rgrp = plane->group;
        unsigned int index = plane->hwindex;
 
-       /* According to the datasheet the Y position is expressed in raster line
-        * units. However, 32bpp formats seem to require a doubled Y position
-        * value. Similarly, for the second plane, NV12 and NV21 formats seem to
+       /* The Y position is expressed in raster line units and must be doubled
+        * for 32bpp formats, according to the R8A7790 datasheet. No mention of
+        * doubling the Y position is found in the R8A7779 datasheet, but the
+        * rule seems to apply there as well.
+        *
+        * Similarly, for the second plane, NV12 and NV21 formats seem to
         * require a halved Y position value.
         */
-       rcar_du_plane_write(rcdu, index, PnSPXR, plane->src_x);
-       rcar_du_plane_write(rcdu, index, PnSPYR, plane->src_y *
+       rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
+       rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
                            (plane->format->bpp == 32 ? 2 : 1));
-       rcar_du_plane_write(rcdu, index, PnDSA0R, plane->dma[0]);
+       rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]);
 
        if (plane->format->planes == 2) {
                index = (index + 1) % 8;
 
-               rcar_du_plane_write(rcdu, index, PnSPXR, plane->src_x);
-               rcar_du_plane_write(rcdu, index, PnSPYR, plane->src_y *
+               rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
+               rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
                                    (plane->format->bpp == 16 ? 2 : 1) / 2);
-               rcar_du_plane_write(rcdu, index, PnDSA0R, plane->dma[1]);
+               rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[1]);
        }
 }
 
@@ -140,7 +145,7 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
 static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
                                     unsigned int index)
 {
-       struct rcar_du_device *rcdu = plane->dev;
+       struct rcar_du_group *rgrp = plane->group;
        u32 colorkey;
        u32 pnmr;
 
@@ -154,9 +159,9 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
         * enable alpha-blending regardless of the X bit value.
         */
        if (plane->format->fourcc != DRM_FORMAT_XRGB1555)
-               rcar_du_plane_write(rcdu, index, PnALPHAR, PnALPHAR_ABIT_0);
+               rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0);
        else
-               rcar_du_plane_write(rcdu, index, PnALPHAR,
+               rcar_du_plane_write(rgrp, index, PnALPHAR,
                                    PnALPHAR_ABIT_X | plane->alpha);
 
        pnmr = PnMR_BM_MD | plane->format->pnmr;
@@ -172,14 +177,14 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
        if (plane->format->fourcc == DRM_FORMAT_YUYV)
                pnmr |= PnMR_YCDF_YUYV;
 
-       rcar_du_plane_write(rcdu, index, PnMR, pnmr);
+       rcar_du_plane_write(rgrp, index, PnMR, pnmr);
 
        switch (plane->format->fourcc) {
        case DRM_FORMAT_RGB565:
                colorkey = ((plane->colorkey & 0xf80000) >> 8)
                         | ((plane->colorkey & 0x00fc00) >> 5)
                         | ((plane->colorkey & 0x0000f8) >> 3);
-               rcar_du_plane_write(rcdu, index, PnTC2R, colorkey);
+               rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
                break;
 
        case DRM_FORMAT_ARGB1555:
@@ -187,12 +192,12 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
                colorkey = ((plane->colorkey & 0xf80000) >> 9)
                         | ((plane->colorkey & 0x00f800) >> 6)
                         | ((plane->colorkey & 0x0000f8) >> 3);
-               rcar_du_plane_write(rcdu, index, PnTC2R, colorkey);
+               rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
                break;
 
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_ARGB8888:
-               rcar_du_plane_write(rcdu, index, PnTC3R,
+               rcar_du_plane_write(rgrp, index, PnTC3R,
                                    PnTC3R_CODE | (plane->colorkey & 0xffffff));
                break;
        }
@@ -201,7 +206,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
 static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
                                  unsigned int index)
 {
-       struct rcar_du_device *rcdu = plane->dev;
+       struct rcar_du_group *rgrp = plane->group;
        u32 ddcr2 = PnDDCR2_CODE;
        u32 ddcr4;
        u32 mwr;
@@ -211,7 +216,7 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
         * The data format is selected by the DDDF field in PnMR and the EDF
         * field in DDCR4.
         */
-       ddcr4 = rcar_du_plane_read(rcdu, index, PnDDCR4);
+       ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
        ddcr4 &= ~PnDDCR4_EDF_MASK;
        ddcr4 |= plane->format->edf | PnDDCR4_CODE;
 
@@ -232,8 +237,8 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
                }
        }
 
-       rcar_du_plane_write(rcdu, index, PnDDCR2, ddcr2);
-       rcar_du_plane_write(rcdu, index, PnDDCR4, ddcr4);
+       rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
+       rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
        /* Memory pitch (expressed in pixels) */
        if (plane->format->planes == 2)
@@ -241,19 +246,19 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
        else
                mwr = plane->pitch * 8 / plane->format->bpp;
 
-       rcar_du_plane_write(rcdu, index, PnMWR, mwr);
+       rcar_du_plane_write(rgrp, index, PnMWR, mwr);
 
        /* Destination position and size */
-       rcar_du_plane_write(rcdu, index, PnDSXR, plane->width);
-       rcar_du_plane_write(rcdu, index, PnDSYR, plane->height);
-       rcar_du_plane_write(rcdu, index, PnDPXR, plane->dst_x);
-       rcar_du_plane_write(rcdu, index, PnDPYR, plane->dst_y);
+       rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
+       rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
+       rcar_du_plane_write(rgrp, index, PnDPXR, plane->dst_x);
+       rcar_du_plane_write(rgrp, index, PnDPYR, plane->dst_y);
 
        /* Wrap-around and blinking, disabled */
-       rcar_du_plane_write(rcdu, index, PnWASPR, 0);
-       rcar_du_plane_write(rcdu, index, PnWAMWR, 4095);
-       rcar_du_plane_write(rcdu, index, PnBTR, 0);
-       rcar_du_plane_write(rcdu, index, PnMLR, 0);
+       rcar_du_plane_write(rgrp, index, PnWASPR, 0);
+       rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
+       rcar_du_plane_write(rgrp, index, PnBTR, 0);
+       rcar_du_plane_write(rgrp, index, PnMLR, 0);
 }
 
 void rcar_du_plane_setup(struct rcar_du_plane *plane)
@@ -273,7 +278,7 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
                       uint32_t src_w, uint32_t src_h)
 {
        struct rcar_du_plane *rplane = to_rcar_plane(plane);
-       struct rcar_du_device *rcdu = plane->dev->dev_private;
+       struct rcar_du_device *rcdu = rplane->group->dev;
        const struct rcar_du_format_info *format;
        unsigned int nplanes;
        int ret;
@@ -316,26 +321,25 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
        rcar_du_plane_compute_base(rplane, fb);
        rcar_du_plane_setup(rplane);
 
-       mutex_lock(&rcdu->planes.lock);
+       mutex_lock(&rplane->group->planes.lock);
        rplane->enabled = true;
        rcar_du_crtc_update_planes(rplane->crtc);
-       mutex_unlock(&rcdu->planes.lock);
+       mutex_unlock(&rplane->group->planes.lock);
 
        return 0;
 }
 
 static int rcar_du_plane_disable(struct drm_plane *plane)
 {
-       struct rcar_du_device *rcdu = plane->dev->dev_private;
        struct rcar_du_plane *rplane = to_rcar_plane(plane);
 
        if (!rplane->enabled)
                return 0;
 
-       mutex_lock(&rcdu->planes.lock);
+       mutex_lock(&rplane->group->planes.lock);
        rplane->enabled = false;
        rcar_du_crtc_update_planes(rplane->crtc);
-       mutex_unlock(&rcdu->planes.lock);
+       mutex_unlock(&rplane->group->planes.lock);
 
        rcar_du_plane_release(rplane);
 
@@ -377,9 +381,7 @@ static void rcar_du_plane_set_colorkey(struct rcar_du_plane *plane,
 static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane,
                                   unsigned int zpos)
 {
-       struct rcar_du_device *rcdu = plane->dev;
-
-       mutex_lock(&rcdu->planes.lock);
+       mutex_lock(&plane->group->planes.lock);
        if (plane->zpos == zpos)
                goto done;
 
@@ -390,21 +392,21 @@ static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane,
        rcar_du_crtc_update_planes(plane->crtc);
 
 done:
-       mutex_unlock(&rcdu->planes.lock);
+       mutex_unlock(&plane->group->planes.lock);
 }
 
 static int rcar_du_plane_set_property(struct drm_plane *plane,
                                      struct drm_property *property,
                                      uint64_t value)
 {
-       struct rcar_du_device *rcdu = plane->dev->dev_private;
        struct rcar_du_plane *rplane = to_rcar_plane(plane);
+       struct rcar_du_group *rgrp = rplane->group;
 
-       if (property == rcdu->planes.alpha)
+       if (property == rgrp->planes.alpha)
                rcar_du_plane_set_alpha(rplane, value);
-       else if (property == rcdu->planes.colorkey)
+       else if (property == rgrp->planes.colorkey)
                rcar_du_plane_set_colorkey(rplane, value);
-       else if (property == rcdu->planes.zpos)
+       else if (property == rgrp->planes.zpos)
                rcar_du_plane_set_zpos(rplane, value);
        else
                return -EINVAL;
@@ -432,37 +434,39 @@ static const uint32_t formats[] = {
        DRM_FORMAT_NV16,
 };
 
-int rcar_du_plane_init(struct rcar_du_device *rcdu)
+int rcar_du_planes_init(struct rcar_du_group *rgrp)
 {
+       struct rcar_du_planes *planes = &rgrp->planes;
+       struct rcar_du_device *rcdu = rgrp->dev;
        unsigned int i;
 
-       mutex_init(&rcdu->planes.lock);
-       rcdu->planes.free = 0xff;
+       mutex_init(&planes->lock);
+       planes->free = 0xff;
 
-       rcdu->planes.alpha =
+       planes->alpha =
                drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255);
-       if (rcdu->planes.alpha == NULL)
+       if (planes->alpha == NULL)
                return -ENOMEM;
 
        /* The color key is expressed as an RGB888 triplet stored in a 32-bit
         * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0)
         * or enable source color keying (1).
         */
-       rcdu->planes.colorkey =
+       planes->colorkey =
                drm_property_create_range(rcdu->ddev, 0, "colorkey",
                                          0, 0x01ffffff);
-       if (rcdu->planes.colorkey == NULL)
+       if (planes->colorkey == NULL)
                return -ENOMEM;
 
-       rcdu->planes.zpos =
+       planes->zpos =
                drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7);
-       if (rcdu->planes.zpos == NULL)
+       if (planes->zpos == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
-               struct rcar_du_plane *plane = &rcdu->planes.planes[i];
+       for (i = 0; i < ARRAY_SIZE(planes->planes); ++i) {
+               struct rcar_du_plane *plane = &planes->planes[i];
 
-               plane->dev = rcdu;
+               plane->group = rgrp;
                plane->hwindex = -1;
                plane->alpha = 255;
                plane->colorkey = RCAR_DU_COLORKEY_NONE;
@@ -472,11 +476,16 @@ int rcar_du_plane_init(struct rcar_du_device *rcdu)
        return 0;
 }
 
-int rcar_du_plane_register(struct rcar_du_device *rcdu)
+int rcar_du_planes_register(struct rcar_du_group *rgrp)
 {
+       struct rcar_du_planes *planes = &rgrp->planes;
+       struct rcar_du_device *rcdu = rgrp->dev;
+       unsigned int crtcs;
        unsigned int i;
        int ret;
 
+       crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
+
        for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) {
                struct rcar_du_kms_plane *plane;
 
@@ -484,23 +493,22 @@ int rcar_du_plane_register(struct rcar_du_device *rcdu)
                if (plane == NULL)
                        return -ENOMEM;
 
-               plane->hwplane = &rcdu->planes.planes[i + 2];
+               plane->hwplane = &planes->planes[i + 2];
                plane->hwplane->zpos = 1;
 
-               ret = drm_plane_init(rcdu->ddev, &plane->plane,
-                                    (1 << rcdu->num_crtcs) - 1,
+               ret = drm_plane_init(rcdu->ddev, &plane->plane, crtcs,
                                     &rcar_du_plane_funcs, formats,
                                     ARRAY_SIZE(formats), false);
                if (ret < 0)
                        return ret;
 
                drm_object_attach_property(&plane->plane.base,
-                                          rcdu->planes.alpha, 255);
+                                          planes->alpha, 255);
                drm_object_attach_property(&plane->plane.base,
-                                          rcdu->planes.colorkey,
+                                          planes->colorkey,
                                           RCAR_DU_COLORKEY_NONE);
                drm_object_attach_property(&plane->plane.base,
-                                          rcdu->planes.zpos, 1);
+                                          planes->zpos, 1);
        }
 
        return 0;
index 5397dba2fe5795fe64844efaedbbfe7ead226435..f94f9ce84998782c9720661d068b78dfacc65dc3 100644 (file)
 #ifndef __RCAR_DU_PLANE_H__
 #define __RCAR_DU_PLANE_H__
 
-struct drm_crtc;
-struct drm_framebuffer;
-struct rcar_du_device;
+#include <linux/mutex.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
 struct rcar_du_format_info;
+struct rcar_du_group;
 
 /* The RCAR DU has 8 hardware planes, shared between KMS planes and CRTCs. As
  * using KMS planes requires at least one of the CRTCs being enabled, no more
@@ -30,7 +33,7 @@ struct rcar_du_format_info;
 #define RCAR_DU_NUM_SW_PLANES          9
 
 struct rcar_du_plane {
-       struct rcar_du_device *dev;
+       struct rcar_du_group *group;
        struct drm_crtc *crtc;
 
        bool enabled;
@@ -54,8 +57,19 @@ struct rcar_du_plane {
        unsigned int dst_y;
 };
 
-int rcar_du_plane_init(struct rcar_du_device *rcdu);
-int rcar_du_plane_register(struct rcar_du_device *rcdu);
+struct rcar_du_planes {
+       struct rcar_du_plane planes[RCAR_DU_NUM_SW_PLANES];
+       unsigned int free;
+       struct mutex lock;
+
+       struct drm_property *alpha;
+       struct drm_property *colorkey;
+       struct drm_property *zpos;
+};
+
+int rcar_du_planes_init(struct rcar_du_group *rgrp);
+int rcar_du_planes_register(struct rcar_du_group *rgrp);
+
 void rcar_du_plane_setup(struct rcar_du_plane *plane);
 void rcar_du_plane_update_base(struct rcar_du_plane *plane);
 void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
index 69f21f19b51cbc14914d00079943b2894440a8d5..73f7347f740bd1f94707990a8d9115fcf57fc518 100644 (file)
 #ifndef __RCAR_DU_REGS_H__
 #define __RCAR_DU_REGS_H__
 
-#define DISP2_REG_OFFSET        0x30000
+#define DU0_REG_OFFSET         0x00000
+#define DU1_REG_OFFSET         0x30000
+#define DU2_REG_OFFSET         0x40000
 
 /* -----------------------------------------------------------------------------
  * Display Control Registers
  */
 
 #define DSYSR                  0x00000 /* display 1 */
-#define D2SYSR                 0x30000 /* display 2 */
 #define DSYSR_ILTS             (1 << 29)
 #define DSYSR_DSEC             (1 << 20)
 #define DSYSR_IUPD             (1 << 16)
@@ -35,7 +36,6 @@
 #define DSYSR_SCM_INT_VIDEO    (3 << 4)
 
 #define DSMR                   0x00004
-#define D2SMR                  0x30004
 #define DSMR_VSPM              (1 << 28)
 #define DSMR_ODPM              (1 << 27)
 #define DSMR_DIPM_DISP         (0 << 25)
@@ -60,7 +60,6 @@
 #define DSMR_CSY_MASK          (3 << 6)
 
 #define DSSR                   0x00008
-#define D2SSR                  0x30008
 #define DSSR_VC1FB_DSA0                (0 << 30)
 #define DSSR_VC1FB_DSA1                (1 << 30)
 #define DSSR_VC1FB_DSA2                (2 << 30)
@@ -80,7 +79,6 @@
 #define DSSR_ADC(n)            (1 << ((n)-1))
 
 #define DSRCR                  0x0000c
-#define D2SRCR                 0x3000c
 #define DSRCR_TVCL             (1 << 15)
 #define DSRCR_FRCL             (1 << 14)
 #define DSRCR_VBCL             (1 << 11)
@@ -90,7 +88,6 @@
 #define DSRCR_MASK             0x0000cbff
 
 #define DIER                   0x00010
-#define D2IER                  0x30010
 #define DIER_TVE               (1 << 15)
 #define DIER_FRE               (1 << 14)
 #define DIER_VBE               (1 << 11)
 #define DPPR_BPP32             (DPPR_BPP32_P1 | DPPR_BPP32_P2) /* plane1 & 2 */
 
 #define DEFR                   0x00020
-#define D2EFR                  0x30020
 #define DEFR_CODE              (0x7773 << 16)
 #define DEFR_EXSL              (1 << 12)
 #define DEFR_EXVL              (1 << 11)
 #define DCPCR_DCE              (1 << 0)
 
 #define DEFR2                  0x00034
-#define D2EFR2                 0x30034
 #define DEFR2_CODE             (0x7775 << 16)
 #define DEFR2_DEFE2G           (1 << 0)
 
 #define DEFR3                  0x00038
-#define D2EFR3                 0x30038
 #define DEFR3_CODE             (0x7776 << 16)
 #define DEFR3_EVDA             (1 << 14)
 #define DEFR3_EVDM_1           (1 << 12)
 #define DEFR3_DEFE3            (1 << 0)
 
 #define DEFR4                  0x0003c
-#define D2EFR4                 0x3003c
 #define DEFR4_CODE             (0x7777 << 16)
 #define DEFR4_LRUO             (1 << 5)
 #define DEFR4_SPCE             (1 << 4)
 #define DEFR6_MLOS1            (1 << 2)
 #define DEFR6_DEFAULT          (DEFR6_CODE | DEFR6_TCNE2)
 
+/* -----------------------------------------------------------------------------
+ * R8A7790-only Control Registers
+ */
+
+#define DD1SSR                 0x20008
+#define DD1SSR_TVR             (1 << 15)
+#define DD1SSR_FRM             (1 << 14)
+#define DD1SSR_BUF             (1 << 12)
+#define DD1SSR_VBK             (1 << 11)
+#define DD1SSR_RINT            (1 << 9)
+#define DD1SSR_HBK             (1 << 8)
+#define DD1SSR_ADC(n)          (1 << ((n)-1))
+
+#define DD1SRCR                        0x2000c
+#define DD1SRCR_TVR            (1 << 15)
+#define DD1SRCR_FRM            (1 << 14)
+#define DD1SRCR_BUF            (1 << 12)
+#define DD1SRCR_VBK            (1 << 11)
+#define DD1SRCR_RINT           (1 << 9)
+#define DD1SRCR_HBK            (1 << 8)
+#define DD1SRCR_ADC(n)         (1 << ((n)-1))
+
+#define DD1IER                 0x20010
+#define DD1IER_TVR             (1 << 15)
+#define DD1IER_FRM             (1 << 14)
+#define DD1IER_BUF             (1 << 12)
+#define DD1IER_VBK             (1 << 11)
+#define DD1IER_RINT            (1 << 9)
+#define DD1IER_HBK             (1 << 8)
+#define DD1IER_ADC(n)          (1 << ((n)-1))
+
+#define DEFR8                  0x20020
+#define DEFR8_CODE             (0x7790 << 16)
+#define DEFR8_VSCS             (1 << 6)
+#define DEFR8_DRGBS_DU(n)      ((n) << 4)
+#define DEFR8_DRGBS_MASK       (3 << 4)
+#define DEFR8_DEFE8            (1 << 0)
+
+#define DOFLR                  0x20024
+#define DOFLR_CODE             (0x7790 << 16)
+#define DOFLR_HSYCFL1          (1 << 13)
+#define DOFLR_VSYCFL1          (1 << 12)
+#define DOFLR_ODDFL1           (1 << 11)
+#define DOFLR_DISPFL1          (1 << 10)
+#define DOFLR_CDEFL1           (1 << 9)
+#define DOFLR_RGBFL1           (1 << 8)
+#define DOFLR_HSYCFL0          (1 << 5)
+#define DOFLR_VSYCFL0          (1 << 4)
+#define DOFLR_ODDFL0           (1 << 3)
+#define DOFLR_DISPFL0          (1 << 2)
+#define DOFLR_CDEFL0           (1 << 1)
+#define DOFLR_RGBFL0           (1 << 0)
+
+#define DIDSR                  0x20028
+#define DIDSR_CODE             (0x7790 << 16)
+#define DIDSR_LCDS_DCLKIN(n)   (0 << (8 + (n) * 2))
+#define DIDSR_LCDS_LVDS0(n)    (2 << (8 + (n) * 2))
+#define DIDSR_LCDS_LVDS1(n)    (3 << (8 + (n) * 2))
+#define DIDSR_LCDS_MASK(n)     (3 << (8 + (n) * 2))
+#define DIDSR_PCDS_CLK(n, clk) (clk << ((n) * 2))
+#define DIDSR_PCDS_MASK(n)     (3 << ((n) * 2))
+
 /* -----------------------------------------------------------------------------
  * Display Timing Generation Registers
  */
 #define APnMR_BM_AD            (2 << 4)        /* Auto Display Change Mode */
 
 #define APnMWR                 0x0a104
+
+#define APnDSXR                        0x0a110
+#define APnDSYR                        0x0a114
+#define APnDPXR                        0x0a118
+#define APnDPYR                        0x0a11c
+
 #define APnDSA0R               0x0a120
 #define APnDSA1R               0x0a124
 #define APnDSA2R               0x0a128
+
+#define APnSPXR                        0x0a130
+#define APnSPYR                        0x0a134
+#define APnWASPR               0x0a138
+#define APnWAMWR               0x0a13c
+
+#define APnBTR                 0x0a140
+
 #define APnMLR                 0x0a150
+#define APnSWAPR               0x0a180
 
 /* -----------------------------------------------------------------------------
  * Display Capture Registers
  */
 
+#define DCMR                   0x0c100
 #define DCMWR                  0x0c104
-#define DC2MWR                 0x0c204
 #define DCSAR                  0x0c120
-#define DC2SAR                 0x0c220
 #define DCMLR                  0x0c150
-#define DC2MLR                 0x0c250
 
 /* -----------------------------------------------------------------------------
  * Color Palette Registers
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vga.c b/drivers/gpu/drm/rcar-du/rcar_du_vga.c
deleted file mode 100644 (file)
index 327289e..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * rcar_du_vga.c  --  R-Car Display Unit VGA DAC and Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_vga.h"
-
-/* -----------------------------------------------------------------------------
- * Connector
- */
-
-static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
-{
-       return 0;
-}
-
-static int rcar_du_vga_connector_mode_valid(struct drm_connector *connector,
-                                           struct drm_display_mode *mode)
-{
-       return MODE_OK;
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-       .get_modes = rcar_du_vga_connector_get_modes,
-       .mode_valid = rcar_du_vga_connector_mode_valid,
-       .best_encoder = rcar_du_connector_best_encoder,
-};
-
-static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
-{
-       drm_sysfs_connector_remove(connector);
-       drm_connector_cleanup(connector);
-}
-
-static enum drm_connector_status
-rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
-{
-       return connector_status_unknown;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-       .dpms = drm_helper_connector_dpms,
-       .detect = rcar_du_vga_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = rcar_du_vga_connector_destroy,
-};
-
-static int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-                                     struct rcar_du_encoder *renc)
-{
-       struct rcar_du_connector *rcon;
-       struct drm_connector *connector;
-       int ret;
-
-       rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
-       if (rcon == NULL)
-               return -ENOMEM;
-
-       connector = &rcon->connector;
-       connector->display_info.width_mm = 0;
-       connector->display_info.height_mm = 0;
-
-       ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-                                DRM_MODE_CONNECTOR_VGA);
-       if (ret < 0)
-               return ret;
-
-       drm_connector_helper_add(connector, &connector_helper_funcs);
-       ret = drm_sysfs_connector_add(connector);
-       if (ret < 0)
-               return ret;
-
-       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-       drm_object_property_set_value(&connector->base,
-               rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-       ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
-       if (ret < 0)
-               return ret;
-
-       connector->encoder = &renc->encoder;
-       rcon->encoder = renc;
-
-       return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * Encoder
- */
-
-static void rcar_du_vga_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-}
-
-static bool rcar_du_vga_encoder_mode_fixup(struct drm_encoder *encoder,
-                                          const struct drm_display_mode *mode,
-                                          struct drm_display_mode *adjusted_mode)
-{
-       return true;
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-       .dpms = rcar_du_vga_encoder_dpms,
-       .mode_fixup = rcar_du_vga_encoder_mode_fixup,
-       .prepare = rcar_du_encoder_mode_prepare,
-       .commit = rcar_du_encoder_mode_commit,
-       .mode_set = rcar_du_encoder_mode_set,
-};
-
-static const struct drm_encoder_funcs encoder_funcs = {
-       .destroy = drm_encoder_cleanup,
-};
-
-int rcar_du_vga_init(struct rcar_du_device *rcdu,
-                    const struct rcar_du_encoder_vga_data *data,
-                    unsigned int output)
-{
-       struct rcar_du_encoder *renc;
-       int ret;
-
-       renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
-       if (renc == NULL)
-               return -ENOMEM;
-
-       renc->output = output;
-
-       ret = drm_encoder_init(rcdu->ddev, &renc->encoder, &encoder_funcs,
-                              DRM_MODE_ENCODER_DAC);
-       if (ret < 0)
-               return ret;
-
-       drm_encoder_helper_add(&renc->encoder, &encoder_helper_funcs);
-
-       return rcar_du_vga_connector_init(rcdu, renc);
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vga.h b/drivers/gpu/drm/rcar-du/rcar_du_vga.h
deleted file mode 100644 (file)
index 66b4d2d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * rcar_du_vga.h  --  R-Car Display Unit VGA DAC and Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_VGA_H__
-#define __RCAR_DU_VGA_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder_vga_data;
-
-int rcar_du_vga_init(struct rcar_du_device *rcdu,
-                    const struct rcar_du_encoder_vga_data *data,
-                    unsigned int output);
-
-#endif /* __RCAR_DU_VGA_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
new file mode 100644 (file)
index 0000000..41d563a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * rcar_du_vgacon.c  --  R-Car Display Unit VGA Connector
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
+#include "rcar_du_kms.h"
+#include "rcar_du_vgacon.h"
+
+static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
+{
+       return 0;
+}
+
+static int rcar_du_vga_connector_mode_valid(struct drm_connector *connector,
+                                           struct drm_display_mode *mode)
+{
+       return MODE_OK;
+}
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+       .get_modes = rcar_du_vga_connector_get_modes,
+       .mode_valid = rcar_du_vga_connector_mode_valid,
+       .best_encoder = rcar_du_connector_best_encoder,
+};
+
+static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
+{
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
+{
+       return connector_status_connected;
+}
+
+static const struct drm_connector_funcs connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = rcar_du_vga_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = rcar_du_vga_connector_destroy,
+};
+
+int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
+                              struct rcar_du_encoder *renc)
+{
+       struct rcar_du_connector *rcon;
+       struct drm_connector *connector;
+       int ret;
+
+       rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
+       if (rcon == NULL)
+               return -ENOMEM;
+
+       connector = &rcon->connector;
+       connector->display_info.width_mm = 0;
+       connector->display_info.height_mm = 0;
+
+       ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
+                                DRM_MODE_CONNECTOR_VGA);
+       if (ret < 0)
+               return ret;
+
+       drm_connector_helper_add(connector, &connector_helper_funcs);
+       ret = drm_sysfs_connector_add(connector);
+       if (ret < 0)
+               return ret;
+
+       drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+       drm_object_property_set_value(&connector->base,
+               rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+
+       ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
+       if (ret < 0)
+               return ret;
+
+       connector->encoder = &renc->encoder;
+       rcon->encoder = renc;
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
new file mode 100644 (file)
index 0000000..b12b0cf
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * rcar_du_vgacon.h  --  R-Car Display Unit VGA Connector
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_VGACON_H__
+#define __RCAR_DU_VGACON_H__
+
+struct rcar_du_device;
+struct rcar_du_encoder;
+
+int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
+                              struct rcar_du_encoder *renc);
+
+#endif /* __RCAR_DU_VGACON_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
new file mode 100644 (file)
index 0000000..77cf928
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * rcar_lvds_regs.h  --  R-Car LVDS Interface Registers Definitions
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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 __RCAR_LVDS_REGS_H__
+#define __RCAR_LVDS_REGS_H__
+
+#define LVDCR0                         0x0000
+#define LVDCR0_DUSEL                   (1 << 15)
+#define LVDCR0_DMD                     (1 << 12)
+#define LVDCR0_LVMD_MASK               (0xf << 8)
+#define LVDCR0_LVMD_SHIFT              8
+#define LVDCR0_PLLEN                   (1 << 4)
+#define LVDCR0_BEN                     (1 << 2)
+#define LVDCR0_LVEN                    (1 << 1)
+#define LVDCR0_LVRES                   (1 << 0)
+
+#define LVDCR1                         0x0004
+#define LVDCR1_CKSEL                   (1 << 15)
+#define LVDCR1_CHSTBY(n)               (3 << (2 + (n) * 2))
+#define LVDCR1_CLKSTBY                 (3 << 0)
+
+#define LVDPLLCR                       0x0008
+#define LVDPLLCR_CEEN                  (1 << 14)
+#define LVDPLLCR_FBEN                  (1 << 13)
+#define LVDPLLCR_COSEL                 (1 << 12)
+#define LVDPLLCR_PLLDLYCNT_150M                (0x1bf << 0)
+#define LVDPLLCR_PLLDLYCNT_121M                (0x22c << 0)
+#define LVDPLLCR_PLLDLYCNT_60M         (0x77b << 0)
+#define LVDPLLCR_PLLDLYCNT_38M         (0x69a << 0)
+#define LVDPLLCR_PLLDLYCNT_MASK                (0x7ff << 0)
+
+#define LVDCTRCR                       0x000c
+#define LVDCTRCR_CTR3SEL_ZERO          (0 << 12)
+#define LVDCTRCR_CTR3SEL_ODD           (1 << 12)
+#define LVDCTRCR_CTR3SEL_CDE           (2 << 12)
+#define LVDCTRCR_CTR3SEL_MASK          (7 << 12)
+#define LVDCTRCR_CTR2SEL_DISP          (0 << 8)
+#define LVDCTRCR_CTR2SEL_ODD           (1 << 8)
+#define LVDCTRCR_CTR2SEL_CDE           (2 << 8)
+#define LVDCTRCR_CTR2SEL_HSYNC         (3 << 8)
+#define LVDCTRCR_CTR2SEL_VSYNC         (4 << 8)
+#define LVDCTRCR_CTR2SEL_MASK          (7 << 8)
+#define LVDCTRCR_CTR1SEL_VSYNC         (0 << 4)
+#define LVDCTRCR_CTR1SEL_DISP          (1 << 4)
+#define LVDCTRCR_CTR1SEL_ODD           (2 << 4)
+#define LVDCTRCR_CTR1SEL_CDE           (3 << 4)
+#define LVDCTRCR_CTR1SEL_HSYNC         (4 << 4)
+#define LVDCTRCR_CTR1SEL_MASK          (7 << 4)
+#define LVDCTRCR_CTR0SEL_HSYNC         (0 << 0)
+#define LVDCTRCR_CTR0SEL_VSYNC         (1 << 0)
+#define LVDCTRCR_CTR0SEL_DISP          (2 << 0)
+#define LVDCTRCR_CTR0SEL_ODD           (3 << 0)
+#define LVDCTRCR_CTR0SEL_CDE           (4 << 0)
+#define LVDCTRCR_CTR0SEL_MASK          (7 << 0)
+
+#define LVDCHCR                                0x0010
+#define LVDCHCR_CHSEL_CH(n, c)         ((((c) - (n)) & 3) << ((n) * 4))
+#define LVDCHCR_CHSEL_MASK(n)          (3 << ((n) * 4))
+
+#endif /* __RCAR_LVDS_REGS_H__ */
index 4c605c70ebf9ed858d014d94383ebfab86851b1f..deb5c25305aff4622ceb8f84a1598902e484a6ce 100644 (file)
@@ -562,7 +562,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
                                struct hv_hotadd_state *has)
 {
        int ret = 0;
-       int i, nid, t;
+       int i, nid;
        unsigned long start_pfn;
        unsigned long processed_pfn;
        unsigned long total_pfn = pfn_count;
@@ -607,14 +607,11 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
 
                /*
                 * Wait for the memory block to be onlined.
+                * Since the hot add has succeeded, it is ok to
+                * proceed even if the pages in the hot added region
+                * have not been "onlined" within the allowed time.
                 */
-               t = wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
-               if (t == 0) {
-                       pr_info("hot_add memory timedout\n");
-                       has->ha_end_pfn -= HA_CHUNK;
-                       has->covered_end_pfn -=  processed_pfn;
-                       break;
-               }
+               wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
 
        }
 
@@ -978,6 +975,14 @@ static void post_status(struct hv_dynmem_device *dm)
                                dm->num_pages_ballooned +
                                compute_balloon_floor();
 
+       /*
+        * If our transaction ID is no longer current, just don't
+        * send the status. This can happen if we were interrupted
+        * after we picked our transaction ID.
+        */
+       if (status.hdr.trans_id != atomic_read(&trans_id))
+               return;
+
        vmbus_sendpacket(dm->dev->channel, &status,
                                sizeof(struct dm_status),
                                (unsigned long)NULL,
index a2464bf07c49b03342c0dfcd79852cc0a232a703..e8e071fc1d6d1ab265d858772fc94bbd5cd8930c 100644 (file)
@@ -690,7 +690,7 @@ int vmbus_device_register(struct hv_device *child_device_obj)
        if (ret)
                pr_err("Unable to register child device\n");
        else
-               pr_info("child device %s registered\n",
+               pr_debug("child device %s registered\n",
                        dev_name(&child_device_obj->device));
 
        return ret;
@@ -702,14 +702,14 @@ int vmbus_device_register(struct hv_device *child_device_obj)
  */
 void vmbus_device_unregister(struct hv_device *device_obj)
 {
+       pr_debug("child device %s unregistered\n",
+               dev_name(&device_obj->device));
+
        /*
         * Kick off the process of unregistering the device.
         * This will call vmbus_remove() and eventually vmbus_device_release()
         */
        device_unregister(&device_obj->device);
-
-       pr_info("child device %s unregistered\n",
-               dev_name(&device_obj->device));
 }
 
 
index 957a719e8c2f1545073d2d897a00ffdf17321878..df7b0a06b0ea2d820aec6ad5a752a13bb64e13e8 100644 (file)
@@ -2290,12 +2290,18 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
        d = r10_bio->devs[1].devnum;
        wbio = r10_bio->devs[1].bio;
        wbio2 = r10_bio->devs[1].repl_bio;
+       /* Need to test wbio2->bi_end_io before we call
+        * generic_make_request as if the former is NULL,
+        * the latter is free to free wbio2.
+        */
+       if (wbio2 && !wbio2->bi_end_io)
+               wbio2 = NULL;
        if (wbio->bi_end_io) {
                atomic_inc(&conf->mirrors[d].rdev->nr_pending);
                md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio));
                generic_make_request(wbio);
        }
-       if (wbio2 && wbio2->bi_end_io) {
+       if (wbio2) {
                atomic_inc(&conf->mirrors[d].replacement->nr_pending);
                md_sync_acct(conf->mirrors[d].replacement->bdev,
                             bio_sectors(wbio2));
index 2bf094a587cb8ff2efb7e1bcabe6f40cd7b52602..78ea44336e75e06d5769b4a6158f2a1e506214e0 100644 (file)
@@ -3462,6 +3462,7 @@ static void handle_stripe(struct stripe_head *sh)
                    test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
                        set_bit(STRIPE_SYNCING, &sh->state);
                        clear_bit(STRIPE_INSYNC, &sh->state);
+                       clear_bit(STRIPE_REPLACED, &sh->state);
                }
                spin_unlock(&sh->stripe_lock);
        }
@@ -3607,19 +3608,23 @@ static void handle_stripe(struct stripe_head *sh)
                        handle_parity_checks5(conf, sh, &s, disks);
        }
 
-       if (s.replacing && s.locked == 0
-           && !test_bit(STRIPE_INSYNC, &sh->state)) {
+       if ((s.replacing || s.syncing) && s.locked == 0
+           && !test_bit(STRIPE_COMPUTE_RUN, &sh->state)
+           && !test_bit(STRIPE_REPLACED, &sh->state)) {
                /* Write out to replacement devices where possible */
                for (i = 0; i < conf->raid_disks; i++)
-                       if (test_bit(R5_UPTODATE, &sh->dev[i].flags) &&
-                           test_bit(R5_NeedReplace, &sh->dev[i].flags)) {
+                       if (test_bit(R5_NeedReplace, &sh->dev[i].flags)) {
+                               WARN_ON(!test_bit(R5_UPTODATE, &sh->dev[i].flags));
                                set_bit(R5_WantReplace, &sh->dev[i].flags);
                                set_bit(R5_LOCKED, &sh->dev[i].flags);
                                s.locked++;
                        }
-               set_bit(STRIPE_INSYNC, &sh->state);
+               if (s.replacing)
+                       set_bit(STRIPE_INSYNC, &sh->state);
+               set_bit(STRIPE_REPLACED, &sh->state);
        }
        if ((s.syncing || s.replacing) && s.locked == 0 &&
+           !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
            test_bit(STRIPE_INSYNC, &sh->state)) {
                md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
                clear_bit(STRIPE_SYNCING, &sh->state);
index b0b663b119a8f324ba7fa3b58953b42c81030fa4..70c49329ca9a23fbbad73061477ac0a0cfe80e6e 100644 (file)
@@ -306,6 +306,7 @@ enum {
        STRIPE_SYNC_REQUESTED,
        STRIPE_SYNCING,
        STRIPE_INSYNC,
+       STRIPE_REPLACED,
        STRIPE_PREREAD_ACTIVE,
        STRIPE_DELAYED,
        STRIPE_DEGRADED,
index f7b90661e3213668310274b445f51d972ef4b9a5..e068a76a5f6f268bf183097007efb3aa571acb89 100644 (file)
@@ -66,14 +66,19 @@ EXPORT_SYMBOL(ssc_request);
 
 void ssc_free(struct ssc_device *ssc)
 {
+       bool disable_clk = true;
+
        spin_lock(&user_lock);
-       if (ssc->user) {
+       if (ssc->user)
                ssc->user--;
-               clk_disable_unprepare(ssc->clk);
-       } else {
+       else {
+               disable_clk = false;
                dev_dbg(&ssc->pdev->dev, "device already free\n");
        }
        spin_unlock(&user_lock);
+
+       if (disable_clk)
+               clk_disable_unprepare(ssc->clk);
 }
 EXPORT_SYMBOL(ssc_free);
 
index f9296abcf02ad88dd2b2fd6675c8c27bd7e0eda7..6127ab64bb399323e57e418e9742c2f5b8a9d86d 100644 (file)
@@ -167,7 +167,7 @@ int mei_hbm_start_req(struct mei_device *dev)
 
        dev->hbm_state = MEI_HBM_IDLE;
        if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
-               dev_err(&dev->pdev->dev, "version message writet failed\n");
+               dev_err(&dev->pdev->dev, "version message write failed\n");
                dev->dev_state = MEI_DEV_RESETTING;
                mei_reset(dev, 1);
                return -ENODEV;
index e4f8dec4dc3ccf134317abbd70594f503e9a5344..b22c7e2472254b89dbacc20c20772dfd297d575e 100644 (file)
@@ -239,14 +239,18 @@ static int mei_me_hw_ready_wait(struct mei_device *dev)
        if (mei_me_hw_is_ready(dev))
                return 0;
 
+       dev->recvd_hw_ready = false;
        mutex_unlock(&dev->device_lock);
        err = wait_event_interruptible_timeout(dev->wait_hw_ready,
-                       dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT);
+                       dev->recvd_hw_ready,
+                       mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
        mutex_lock(&dev->device_lock);
        if (!err && !dev->recvd_hw_ready) {
+               if (!err)
+                       err = -ETIMEDOUT;
                dev_err(&dev->pdev->dev,
-                       "wait hw ready failed. status = 0x%x\n", err);
-               return -ETIMEDOUT;
+                       "wait hw ready failed. status = %d\n", err);
+               return err;
        }
 
        dev->recvd_hw_ready = false;
@@ -483,7 +487,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
        /* check if ME wants a reset */
        if (!mei_hw_is_ready(dev) &&
            dev->dev_state != MEI_DEV_RESETTING &&
-           dev->dev_state != MEI_DEV_INITIALIZING) {
+           dev->dev_state != MEI_DEV_INITIALIZING &&
+           dev->dev_state != MEI_DEV_POWER_DOWN &&
+           dev->dev_state != MEI_DEV_POWER_UP) {
                dev_dbg(&dev->pdev->dev, "FW not ready.\n");
                mei_reset(dev, 1);
                mutex_unlock(&dev->device_lock);
index ed1d75203af6e702de1e7a5c3fbdb6b6e8a765d6..e6f16f83ecdee479bfd679f169e078866bd3354a 100644 (file)
@@ -148,7 +148,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 
        dev->hbm_state = MEI_HBM_IDLE;
 
-       if (dev->dev_state != MEI_DEV_INITIALIZING) {
+       if (dev->dev_state != MEI_DEV_INITIALIZING &&
+           dev->dev_state != MEI_DEV_POWER_UP) {
                if (dev->dev_state != MEI_DEV_DISABLED &&
                    dev->dev_state != MEI_DEV_POWER_DOWN)
                        dev->dev_state = MEI_DEV_RESETTING;
index 847b1996ce8ea105eeec31366dad87621a320ee2..2c5a91bb8ec3dbcf1433e114625e94b7d4c3cfe6 100644 (file)
@@ -128,7 +128,7 @@ static inline int pxamci_set_power(struct pxamci_host *host,
                               !!on ^ host->pdata->gpio_power_invert);
        }
        if (!host->vcc && host->pdata && host->pdata->setpower)
-               host->pdata->setpower(mmc_dev(host->mmc), vdd);
+               return host->pdata->setpower(mmc_dev(host->mmc), vdd);
 
        return 0;
 }
index a3c1c5aae6a9eaa5de0ecd0dd0335771ac8f7fab..1264923ade0f2c7973528080d3fa75167b6be0b4 100644 (file)
@@ -345,6 +345,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
        if (r && irq) {
                const char *name = NULL;
 
+               memset(r, 0, sizeof(*r));
                /*
                 * Get optional "interrupts-names" property to add a name
                 * to the resource.
@@ -482,8 +483,9 @@ void __init of_irq_init(const struct of_device_id *matches)
                }
 
                /* Get the next pending parent that might have children */
-               desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
-               if (list_empty(&intc_parent_list) || !desc) {
+               desc = list_first_entry_or_null(&intc_parent_list,
+                                               typeof(*desc), list);
+               if (!desc) {
                        pr_err("of_irq_init: children remain, but no parents\n");
                        break;
                }
index b29e20b7862f168673b3ad980200dd3c80fff175..bb7af78e4eedd359a08db0fab40682a82abac5e1 100644 (file)
@@ -388,7 +388,6 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
        /* Remove the EADS bridge device itself */
        BUG_ON(!bus->self);
        pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
-       eeh_remove_bus_device(bus->self, true);
        pci_stop_and_remove_bus_device(bus->self);
 
        return 0;
index 5b272bfd261d6803fad6eaac61a3fa28dab4e767..2a00239661b3c27ec979802a3f040f92f2276060 100644 (file)
@@ -1193,6 +1193,7 @@ void pinctrl_unregister_map(struct pinctrl_map const *map)
        list_for_each_entry(maps_node, &pinctrl_maps, node) {
                if (maps_node->maps == map) {
                        list_del(&maps_node->node);
+                       kfree(maps_node);
                        mutex_unlock(&pinctrl_maps_mutex);
                        return;
                }
index 6866548fab31669d5141a7c8af21c10e0caa895d..7323cca440b5929ef7248d6d73662d200c01109b 100644 (file)
@@ -1483,6 +1483,7 @@ static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
        return ret;
 }
 
+#ifdef CONFIG_PM
 static int pinctrl_single_suspend(struct platform_device *pdev,
                                        pm_message_t state)
 {
@@ -1505,6 +1506,7 @@ static int pinctrl_single_resume(struct platform_device *pdev)
 
        return pinctrl_force_default(pcs->pctl);
 }
+#endif
 
 static int pcs_probe(struct platform_device *pdev)
 {
index 7956df58d751a3231db71b2c4f8c00f0cb231b7d..31f7d0e04aaaaa6f335342ee99b5df269e792beb 100644 (file)
@@ -3785,6 +3785,7 @@ static const struct regulator_desc sh73a0_vccq_mc0_desc = {
 
 static struct regulator_consumer_supply sh73a0_vccq_mc0_consumers[] = {
        REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
+       REGULATOR_SUPPLY("vqmmc", "ee100000.sdhi"),
 };
 
 static const struct regulator_init_data sh73a0_vccq_mc0_init_data = {
index 1fa39a4441717e233c8844c0a7e72357356ece0d..867c9681763cab5ad42790dd98eb6137745c0d87 100644 (file)
@@ -496,7 +496,7 @@ static const unsigned sdmmc5_pins[] = { 24, 25, 26 };
 static const struct sirfsoc_muxmask usp0_muxmask[] = {
        {
                .group = 1,
-               .mask = BIT(19) | BIT(20) | BIT(21) | BIT(22),
+               .mask = BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23),
        },
 };
 
@@ -507,8 +507,21 @@ static const struct sirfsoc_padmux usp0_padmux = {
        .funcval = 0,
 };
 
-static const unsigned usp0_pins[] = { 51, 52, 53, 54 };
+static const unsigned usp0_pins[] = { 51, 52, 53, 54, 55 };
 
+static const struct sirfsoc_muxmask usp0_uart_nostreamctrl_muxmask[] = {
+       {
+               .group = 1,
+               .mask = BIT(20) | BIT(21),
+       },
+};
+
+static const struct sirfsoc_padmux usp0_uart_nostreamctrl_padmux = {
+       .muxmask_counts = ARRAY_SIZE(usp0_uart_nostreamctrl_muxmask),
+       .muxmask = usp0_uart_nostreamctrl_muxmask,
+};
+
+static const unsigned usp0_uart_nostreamctrl_pins[] = { 52, 53 };
 static const struct sirfsoc_muxmask usp1_muxmask[] = {
        {
                .group = 0,
@@ -822,6 +835,8 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
        SIRFSOC_PIN_GROUP("uart2grp", uart2_pins),
        SIRFSOC_PIN_GROUP("uart2_nostreamctrlgrp", uart2_nostreamctrl_pins),
        SIRFSOC_PIN_GROUP("usp0grp", usp0_pins),
+       SIRFSOC_PIN_GROUP("usp0_uart_nostreamctrl_grp",
+                                       usp0_uart_nostreamctrl_pins),
        SIRFSOC_PIN_GROUP("usp1grp", usp1_pins),
        SIRFSOC_PIN_GROUP("i2c0grp", i2c0_pins),
        SIRFSOC_PIN_GROUP("i2c1grp", i2c1_pins),
@@ -862,6 +877,8 @@ static const char * const uart0grp[] = { "uart0grp" };
 static const char * const uart1grp[] = { "uart1grp" };
 static const char * const uart2grp[] = { "uart2grp" };
 static const char * const uart2_nostreamctrlgrp[] = { "uart2_nostreamctrlgrp" };
+static const char * const usp0_uart_nostreamctrl_grp[] = {
+                                       "usp0_uart_nostreamctrl_grp" };
 static const char * const usp0grp[] = { "usp0grp" };
 static const char * const usp1grp[] = { "usp1grp" };
 static const char * const i2c0grp[] = { "i2c0grp" };
@@ -904,6 +921,9 @@ static const struct sirfsoc_pmx_func sirfsoc_pmx_functions[] = {
        SIRFSOC_PMX_FUNCTION("uart2", uart2grp, uart2_padmux),
        SIRFSOC_PMX_FUNCTION("uart2_nostreamctrl", uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux),
        SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux),
+       SIRFSOC_PMX_FUNCTION("usp0_uart_nostreamctrl",
+                                               usp0_uart_nostreamctrl_grp,
+                                               usp0_uart_nostreamctrl_padmux),
        SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux),
        SIRFSOC_PMX_FUNCTION("i2c0", i2c0grp, i2c0_padmux),
        SIRFSOC_PMX_FUNCTION("i2c1", i2c1grp, i2c1_padmux),
index 7b082157eb79668b5fa6bcda0b16d6df25cd6acb..99d2930b18c80e319d3c506244c80b6205bab17e 100644 (file)
@@ -185,7 +185,7 @@ static void sci_io_request_build_ssp_command_iu(struct isci_request *ireq)
        cmd_iu->_r_c = 0;
 
        sci_swab32_cpy(&cmd_iu->cdb, task->ssp_task.cmd->cmnd,
-                      task->ssp_task.cmd->cmd_len / sizeof(u32));
+                      (task->ssp_task.cmd->cmd_len+3) / sizeof(u32));
 }
 
 static void sci_task_request_build_ssp_task_iu(struct isci_request *ireq)
index 9bb020ac089cddf6b665e8a52f728c95621ece34..0d30ca849e8f71502c9ecddfa9aa539e4e59af0f 100644 (file)
@@ -491,6 +491,7 @@ int isci_task_abort_task(struct sas_task *task)
        struct isci_tmf           tmf;
        int                       ret = TMF_RESP_FUNC_FAILED;
        unsigned long             flags;
+       int                       target_done_already = 0;
 
        /* Get the isci_request reference from the task.  Note that
         * this check does not depend on the pending request list
@@ -505,9 +506,11 @@ int isci_task_abort_task(struct sas_task *task)
        /* If task is already done, the request isn't valid */
        if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
            (task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
-           old_request)
+           old_request) {
                idev = isci_get_device(task->dev->lldd_dev);
-
+               target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET,
+                                              &old_request->flags);
+       }
        spin_unlock(&task->task_state_lock);
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
@@ -561,7 +564,7 @@ int isci_task_abort_task(struct sas_task *task)
 
        if (task->task_proto == SAS_PROTOCOL_SMP ||
            sas_protocol_ata(task->task_proto) ||
-           test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags) ||
+           target_done_already ||
            test_bit(IDEV_GONE, &idev->flags)) {
 
                spin_unlock_irqrestore(&ihost->scic_lock, flags);
index f14665a6293dbb702d9c7c4a98fc135fc6f489eb..6b1b4e91e53f655128edf0235589bd02081963fb 100644 (file)
@@ -1857,11 +1857,16 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
                goto out;
        }
 
-       /* error info record present */
-       if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
+       /*
+        * error info record present; slot->response is 32 bit aligned but may
+        * not be 64 bit aligned, so check for zero in two 32 bit reads
+        */
+       if (unlikely((rx_desc & RXQ_ERR)
+                    && (*((u32 *)slot->response)
+                        || *(((u32 *)slot->response) + 1)))) {
                mv_dprintk("port %d slot %d rx_desc %X has error info"
                        "%016llX.\n", slot->port->sas_port.id, slot_idx,
-                        rx_desc, (u64)(*(u64 *)slot->response));
+                        rx_desc, get_unaligned_le64(slot->response));
                tstat->stat = mvs_slot_err(mvi, task, slot_idx);
                tstat->resp = SAS_TASK_COMPLETE;
                goto out;
index 60e2fb7f2dca7e37512b128bea9b59fd1c9cd579..d6b19dc80bee522a934bb1bb64dd56c1ecad0c51 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <asm/unaligned.h>
 #include <scsi/libsas.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_tcq.h>
index 42ef481db942a79685900c136e7140a199cd8dc4..ef0a5481b9dd46ce0efbad796fa9a6cf04744296 100644 (file)
@@ -419,6 +419,8 @@ qla2x00_start_scsi(srb_t *sp)
                            __constant_cpu_to_le16(CF_SIMPLE_TAG);
                        break;
                }
+       } else {
+               cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
        }
 
        /* Load SCSI command packet. */
@@ -1307,11 +1309,11 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
                    fcp_cmnd->task_attribute = TSK_ORDERED;
                    break;
                default:
-                   fcp_cmnd->task_attribute = 0;
+                   fcp_cmnd->task_attribute = TSK_SIMPLE;
                    break;
                }
        } else {
-               fcp_cmnd->task_attribute = 0;
+               fcp_cmnd->task_attribute = TSK_SIMPLE;
        }
 
        cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
@@ -1525,7 +1527,12 @@ qla24xx_start_scsi(srb_t *sp)
                case ORDERED_QUEUE_TAG:
                        cmd_pkt->task = TSK_ORDERED;
                        break;
+               default:
+                   cmd_pkt->task = TSK_SIMPLE;
+                   break;
                }
+       } else {
+               cmd_pkt->task = TSK_SIMPLE;
        }
 
        /* Load SCSI command packet. */
index 80f39b8b02239ad325143fb3e5e38c9753729ab4..86fcf2c313ad2ef9c5539149bb0006a06bd5c25b 100644 (file)
@@ -838,10 +838,17 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 
 static void sd_unprep_fn(struct request_queue *q, struct request *rq)
 {
+       struct scsi_cmnd *SCpnt = rq->special;
+
        if (rq->cmd_flags & REQ_DISCARD) {
                free_page((unsigned long)rq->buffer);
                rq->buffer = NULL;
        }
+       if (SCpnt->cmnd != rq->cmd) {
+               mempool_free(SCpnt->cmnd, sd_cdb_pool);
+               SCpnt->cmnd = NULL;
+               SCpnt->cmd_len = 0;
+       }
 }
 
 /**
@@ -1720,21 +1727,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
                sd_dif_complete(SCpnt, good_bytes);
 
-       if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
-           == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) {
-
-               /* We have to print a failed command here as the
-                * extended CDB gets freed before scsi_io_completion()
-                * is called.
-                */
-               if (result)
-                       scsi_print_command(SCpnt);
-
-               mempool_free(SCpnt->cmnd, sd_cdb_pool);
-               SCpnt->cmnd = NULL;
-               SCpnt->cmd_len = 0;
-       }
-
        return good_bytes;
 }
 
index 080abf2faf972ab3b999ac58f923c03dbec7e9b8..a8c344422a77d5cce6c34fcadfd7d61781d660bc 100644 (file)
@@ -469,7 +469,7 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
                         unsigned long nr_segs, loff_t ppos)
 {
        struct logger_log *log = file_get_log(iocb->ki_filp);
-       size_t orig = log->w_off;
+       size_t orig;
        struct logger_entry header;
        struct timespec now;
        ssize_t ret = 0;
@@ -490,6 +490,8 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
        mutex_lock(&log->mutex);
 
+       orig = log->w_off;
+
        /*
         * Fix up any readers, pulling them forward to the first readable
         * entry after (what will be) the new write offset. We do this now
index b10f739b7e3e1fcbe16acaf7d66705b59e534441..fa8da9aada3079b6a18fc0189d4fdca36af753c6 100644 (file)
@@ -9,4 +9,4 @@ TODO:
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
 copy:
        Ian Abbott <abbotti@mev.co.uk>
-       Frank Mori Hess <fmhess@users.sourceforge.net>
+       H Hartley Sweeten <hsweeten@visionengravers.com>
index 8647518259f6dd5ab3379babc218d5ef6cf24831..f4a197b2d1fd951f8879b78cd96e6a2cce1f24d3 100644 (file)
@@ -1413,22 +1413,19 @@ static int do_cmd_ioctl(struct comedi_device *dev,
                DPRINTK("subdevice busy\n");
                return -EBUSY;
        }
-       s->busy = file;
 
        /* make sure channel/gain list isn't too long */
        if (cmd.chanlist_len > s->len_chanlist) {
                DPRINTK("channel/gain list too long %u > %d\n",
                        cmd.chanlist_len, s->len_chanlist);
-               ret = -EINVAL;
-               goto cleanup;
+               return -EINVAL;
        }
 
        /* make sure channel/gain list isn't too short */
        if (cmd.chanlist_len < 1) {
                DPRINTK("channel/gain list too short %u < 1\n",
                        cmd.chanlist_len);
-               ret = -EINVAL;
-               goto cleanup;
+               return -EINVAL;
        }
 
        async->cmd = cmd;
@@ -1438,8 +1435,7 @@ static int do_cmd_ioctl(struct comedi_device *dev,
            kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
        if (!async->cmd.chanlist) {
                DPRINTK("allocation failed\n");
-               ret = -ENOMEM;
-               goto cleanup;
+               return -ENOMEM;
        }
 
        if (copy_from_user(async->cmd.chanlist, user_chanlist,
@@ -1491,6 +1487,9 @@ static int do_cmd_ioctl(struct comedi_device *dev,
 
        comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
 
+       /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
+        * comedi_read() or comedi_write() */
+       s->busy = file;
        ret = s->do_cmd(dev, s);
        if (ret == 0)
                return 0;
@@ -1705,6 +1704,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
                           void *file)
 {
        struct comedi_subdevice *s;
+       int ret;
 
        if (arg >= dev->n_subdevices)
                return -EINVAL;
@@ -1721,7 +1721,11 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
        if (s->busy != file)
                return -EBUSY;
 
-       return do_cancel(dev, s);
+       ret = do_cancel(dev, s);
+       if (comedi_get_subdevice_runflags(s) & SRF_USER)
+               wake_up_interruptible(&s->async->wait_head);
+
+       return ret;
 }
 
 /*
@@ -2053,11 +2057,13 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
 
                if (!comedi_is_subdevice_running(s)) {
                        if (count == 0) {
+                               mutex_lock(&dev->mutex);
                                if (comedi_is_subdevice_in_error(s))
                                        retval = -EPIPE;
                                else
                                        retval = 0;
                                do_become_nonbusy(dev, s);
+                               mutex_unlock(&dev->mutex);
                        }
                        break;
                }
@@ -2156,11 +2162,13 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
 
                if (n == 0) {
                        if (!comedi_is_subdevice_running(s)) {
+                               mutex_lock(&dev->mutex);
                                do_become_nonbusy(dev, s);
                                if (comedi_is_subdevice_in_error(s))
                                        retval = -EPIPE;
                                else
                                        retval = 0;
+                               mutex_unlock(&dev->mutex);
                                break;
                        }
                        if (file->f_flags & O_NONBLOCK) {
@@ -2198,9 +2206,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
                buf += n;
                break;          /* makes device work like a pipe */
        }
-       if (comedi_is_subdevice_idle(s) &&
-           async->buf_read_count - async->buf_write_count == 0) {
-               do_become_nonbusy(dev, s);
+       if (comedi_is_subdevice_idle(s)) {
+               mutex_lock(&dev->mutex);
+               if (async->buf_read_count - async->buf_write_count == 0)
+                       do_become_nonbusy(dev, s);
+               mutex_unlock(&dev->mutex);
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&async->wait_head, &wait);
index 5590ebf1da15218c50561fcbd01b0ebc907ce693..817f837b240d656ccf4379bd3f68be4bbf49b867 100644 (file)
@@ -827,11 +827,11 @@ static void usb_alphatrack_disconnect(struct usb_interface *intf)
                mutex_unlock(&dev->mtx);
                usb_alphatrack_delete(dev);
        } else {
+               atomic_set(&dev->writes_pending, 0);
                dev->intf = NULL;
                mutex_unlock(&dev->mtx);
        }
 
-       atomic_set(&dev->writes_pending, 0);
        mutex_unlock(&disconnect_mutex);
 
        dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n",
index b795353e8348a3fcab6d1a01d0472a7168c370a1..cc3692439a5c95fedc0f2c584a52b3d03c0bf391 100644 (file)
@@ -250,8 +250,8 @@ static void send_qos_list(struct nic *nic, struct list_head *head)
 
        list_for_each_entry_safe(entry, n, head, list) {
                list_del(&entry->list);
-               free_qos_entry(entry);
                gdm_wimax_send_tx(entry->skb, entry->dev);
+               free_qos_entry(entry);
        }
 }
 
index 22339059837ff34a15919ca319ede0e0bb1bbf9f..bd0f2fd01db4be91e4f16709c1d788ab1ec2336f 100644 (file)
@@ -33,7 +33,6 @@ config DRM_IMX_TVE
 config DRM_IMX_LDB
        tristate "Support for LVDS displays"
        depends on DRM_IMX
-       select OF_VIDEOMODE
        help
          Choose this to enable the internal LVDS Display Bridge (LDB)
          found on i.MX53 and i.MX6 processors.
index c191ae20356583a48aaba72526a64c92261c073b..41e88abe47af1f518ddf7f0ac955d8ca0812203e 100644 (file)
@@ -1120,8 +1120,11 @@ static int dbll_rmm_alloc(struct dynamic_loader_allocate *this,
           or DYN_EXTERNAL, then mem granularity information is present
           within the section name - only process if there are at least three
           tokens within the section name (just a minor optimization) */
-       if (count >= 3)
-               strict_strtol(sz_last_token, 10, (long *)&req);
+       if (count >= 3) {
+               status = kstrtos32(sz_last_token, 10, &req);
+               if (status)
+                       goto func_cont;
+       }
 
        if ((req == 0) || (req == 1)) {
                if (strcmp(sz_sec_last_token, "DYN_DARAM") == 0) {
index 82c7202fd5cc963668dc8e74caf7dfce11e8f66a..e77fb6ea40c905f3cb72571ef3ca424b44b37440 100644 (file)
@@ -527,8 +527,11 @@ static void zram_reset_device(struct zram *zram)
        size_t index;
        struct zram_meta *meta;
 
-       if (!zram->init_done)
+       down_write(&zram->init_lock);
+       if (!zram->init_done) {
+               up_write(&zram->init_lock);
                return;
+       }
 
        meta = zram->meta;
        zram->init_done = 0;
@@ -549,6 +552,7 @@ static void zram_reset_device(struct zram *zram)
 
        zram->disksize = 0;
        set_capacity(zram->disk, 0);
+       up_write(&zram->init_lock);
 }
 
 static void zram_init_device(struct zram *zram, struct zram_meta *meta)
index 721904f8efa92b8816665410822b355619679f47..946ddd2b3a541990277aabad488843a429e3e6f5 100644 (file)
@@ -193,7 +193,8 @@ static int __init parse_options(struct early_serial8250_device *device,
        if (options) {
                options++;
                device->baud = simple_strtoul(options, NULL, 0);
-               length = min(strcspn(options, " "), sizeof(device->options));
+               length = min(strcspn(options, " ") + 1,
+                            sizeof(device->options));
                strlcpy(device->options, options, length);
        } else {
                device->baud = probe_baud(port);
index 5e3d68917ffed2529c3cd0181d40d7ae95f8ebcd..1456673bcca09b58cc4d1e7c27fd31569b8439bf 100644 (file)
@@ -277,7 +277,7 @@ config SERIAL_TEGRA
        select SERIAL_CORE
        help
          Support for the on-chip UARTs on the NVIDIA Tegra series SOCs
-         providing /dev/ttyHS0, 1, 2, 3 and 4 (note, some machines may not
+         providing /dev/ttyTHS0, 1, 2, 3 and 4 (note, some machines may not
          provide all of these ports, depending on how the serial port
          are enabled). This driver uses the APB DMA to achieve higher baudrate
          and better performance.
index ff171384ea5256cabcf018c3a3dc839279f71392..dc6e96996ead4796eace1ba3bb4b61232f132302 100644 (file)
@@ -3478,7 +3478,7 @@ static int alloc_buf_list(SLMP_INFO *info)
        for ( i = 0; i < info->rx_buf_count; i++ ) {
                /* calculate and store physical address of this buffer entry */
                info->rx_buf_list_ex[i].phys_entry =
-                       info->buffer_list_phys + (i * sizeof(SCABUFSIZE));
+                       info->buffer_list_phys + (i * SCABUFSIZE);
 
                /* calculate and store physical address of */
                /* next entry in cirular list of entries */
index 4191db32f12c2ccf4901287c6ccb1a357c9b552a..4a8a1d68002c0fa1695078c6566c616bf764fa35 100644 (file)
@@ -668,6 +668,15 @@ resubmit:
 static inline int
 hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
 {
+       /* Need to clear both directions for control ep */
+       if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) ==
+                       USB_ENDPOINT_XFER_CONTROL) {
+               int status = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+                               HUB_CLEAR_TT_BUFFER, USB_RT_PORT,
+                               devinfo ^ 0x8000, tt, NULL, 0, 1000);
+               if (status)
+                       return status;
+       }
        return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
                               HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo,
                               tt, NULL, 0, 1000);
@@ -2848,6 +2857,15 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
                                USB_CTRL_SET_TIMEOUT);
 }
 
+/* Count of wakeup-enabled devices at or below udev */
+static unsigned wakeup_enabled_descendants(struct usb_device *udev)
+{
+       struct usb_hub *hub = usb_hub_to_struct_hub(udev);
+
+       return udev->do_remote_wakeup +
+                       (hub ? hub->wakeup_enabled_descendants : 0);
+}
+
 /*
  * usb_port_suspend - suspend a usb device's upstream port
  * @udev: device that's no longer in active use, not a root hub
@@ -2888,8 +2906,8 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  *
- * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
- * suspended only when their bus goes into global suspend (i.e., the root
+ * If Runtime PM isn't enabled or used, non-SuperSpeed devices may not get
+ * suspended until their bus goes into global suspend (i.e., the root
  * hub is suspended).  Nevertheless, we change @udev->state to
  * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
  * upstream port setting is stored in @udev->port_is_suspended.
@@ -2960,15 +2978,21 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
        /* see 7.1.7.6 */
        if (hub_is_superspeed(hub->hdev))
                status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
-       else if (PMSG_IS_AUTO(msg))
-               status = set_port_feature(hub->hdev, port1,
-                                               USB_PORT_FEAT_SUSPEND);
+
        /*
         * For system suspend, we do not need to enable the suspend feature
         * on individual USB-2 ports.  The devices will automatically go
         * into suspend a few ms after the root hub stops sending packets.
         * The USB 2.0 spec calls this "global suspend".
+        *
+        * However, many USB hubs have a bug: They don't relay wakeup requests
+        * from a downstream port if the port's suspend feature isn't on.
+        * Therefore we will turn on the suspend feature if udev or any of its
+        * descendants is enabled for remote wakeup.
         */
+       else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
+               status = set_port_feature(hub->hdev, port1,
+                               USB_PORT_FEAT_SUSPEND);
        else {
                really_suspend = false;
                status = 0;
@@ -3003,15 +3027,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                if (!PMSG_IS_AUTO(msg))
                        status = 0;
        } else {
-               /* device has up to 10 msec to fully suspend */
                dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n",
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""),
                                udev->do_remote_wakeup);
-               usb_set_device_state(udev, USB_STATE_SUSPENDED);
                if (really_suspend) {
                        udev->port_is_suspended = 1;
+
+                       /* device has up to 10 msec to fully suspend */
                        msleep(10);
                }
+               usb_set_device_state(udev, USB_STATE_SUSPENDED);
        }
 
        /*
@@ -3293,7 +3318,11 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
        unsigned                port1;
        int                     status;
 
-       /* Warn if children aren't already suspended */
+       /*
+        * Warn if children aren't already suspended.
+        * Also, add up the number of wakeup-enabled descendants.
+        */
+       hub->wakeup_enabled_descendants = 0;
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
                struct usb_device       *udev;
 
@@ -3303,6 +3332,9 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
                        if (PMSG_IS_AUTO(msg))
                                return -EBUSY;
                }
+               if (udev)
+                       hub->wakeup_enabled_descendants +=
+                                       wakeup_enabled_descendants(udev);
        }
 
        if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
index 6508e02b3dac91718c31dda7e90b6984fed0c898..4e4790dea3439fc10a57b9fac30f73d77245fdf8 100644 (file)
@@ -59,6 +59,9 @@ struct usb_hub {
        struct usb_tt           tt;             /* Transaction Translator */
 
        unsigned                mA_per_port;    /* current for each child */
+#ifdef CONFIG_PM
+       unsigned                wakeup_enabled_descendants;
+#endif
 
        unsigned                limited_power:1;
        unsigned                quiescing:1;
index 757aa18027d05ca0eb198d97d92f1710e8e58def..2378958ea63e01426edbda87183674256a4334ff 100644 (file)
@@ -1,6 +1,6 @@
 config USB_DWC3
        tristate "DesignWare USB3 DRD Core Support"
-       depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
+       depends on (USB || USB_GADGET) && GENERIC_HARDIRQS && HAS_DMA
        select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
        help
          Say Y or M here if your system has a Dual Role SuperSpeed
index c35d49d39b7615f83e7e71a9f009643e33c8d760..358375e0b291098d8be40d65bdfbbff7f97f0826 100644 (file)
@@ -450,7 +450,7 @@ static int dwc3_probe(struct platform_device *pdev)
        }
 
        if (IS_ERR(dwc->usb3_phy)) {
-               ret = PTR_ERR(dwc->usb2_phy);
+               ret = PTR_ERR(dwc->usb3_phy);
 
                /*
                 * if -ENXIO is returned, it means PHY layer wasn't
index b69d322e3cab51c4bcdb784d8f0e3eeda66028e2..27dad993b00706ef5a14a257c40bd353ca6ee560 100644 (file)
@@ -759,8 +759,8 @@ struct dwc3 {
 
 struct dwc3_event_type {
        u32     is_devspec:1;
-       u32     type:6;
-       u32     reserved8_31:25;
+       u32     type:7;
+       u32     reserved8_31:24;
 } __packed;
 
 #define DWC3_DEPEVT_XFERCOMPLETE       0x01
index b5e5b35df49c8ff49ca5817ced0838e79dad9ccf..f77083fedc68d0d1bfc7afb579e6aae96edb1d63 100644 (file)
@@ -1584,6 +1584,7 @@ err1:
        __dwc3_gadget_ep_disable(dwc->eps[0]);
 
 err0:
+       dwc->gadget_driver = NULL;
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return ret;
index 62f6802f6e0fd98bec3aa03abe3d0fff4a1ee191..8e9368330b103a60cc7fb53be21991315c489fd8 100644 (file)
@@ -193,6 +193,7 @@ config USB_FUSB300
           Faraday usb device controller FUSB300 driver
 
 config USB_FOTG210_UDC
+       depends on HAS_DMA
        tristate "Faraday FOTG210 USB Peripheral Controller"
        help
           Faraday USB2.0 OTG controller which can be configured as
@@ -328,13 +329,14 @@ config USB_S3C_HSUDC
 
 config USB_MV_UDC
        tristate "Marvell USB2.0 Device Controller"
-       depends on GENERIC_HARDIRQS
+       depends on GENERIC_HARDIRQS && HAS_DMA
        help
          Marvell Socs (including PXA and MMP series) include a high speed
          USB2.0 OTG controller, which can be configured as high speed or
          full speed USB peripheral.
 
 config USB_MV_U3D
+       depends on HAS_DMA
        tristate "MARVELL PXA2128 USB 3.0 controller"
        help
          MARVELL PXA2128 Processor series include a super speed USB3.0 device
@@ -639,6 +641,7 @@ config USB_CONFIGFS_RNDIS
        depends on USB_CONFIGFS
        depends on NET
        select USB_U_ETHER
+       select USB_U_RNDIS
        select USB_F_RNDIS
        help
           Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
index 073b938f913546793d24443a89dc928982eecaaa..d9a6add0c8526e06778addb733ce3e53da78a291 100644 (file)
@@ -870,8 +870,8 @@ static void clk_on(struct at91_udc *udc)
        if (udc->clocked)
                return;
        udc->clocked = 1;
-       clk_enable(udc->iclk);
-       clk_enable(udc->fclk);
+       clk_prepare_enable(udc->iclk);
+       clk_prepare_enable(udc->fclk);
 }
 
 static void clk_off(struct at91_udc *udc)
@@ -880,8 +880,8 @@ static void clk_off(struct at91_udc *udc)
                return;
        udc->clocked = 0;
        udc->gadget.speed = USB_SPEED_UNKNOWN;
-       clk_disable(udc->fclk);
-       clk_disable(udc->iclk);
+       clk_disable_unprepare(udc->fclk);
+       clk_disable_unprepare(udc->iclk);
 }
 
 /*
@@ -1725,7 +1725,7 @@ static int at91udc_probe(struct platform_device *pdev)
        /* init software state */
        udc = &controller;
        udc->gadget.dev.parent = dev;
-       if (pdev->dev.of_node)
+       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
                at91udc_of_init(udc, pdev->dev.of_node);
        else
                memcpy(&udc->board, dev->platform_data,
@@ -1782,12 +1782,14 @@ static int at91udc_probe(struct platform_device *pdev)
        }
 
        /* don't do anything until we have both gadget driver and VBUS */
-       clk_enable(udc->iclk);
+       retval = clk_prepare_enable(udc->iclk);
+       if (retval)
+               goto fail1;
        at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
        at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
        /* Clear all pending interrupts - UDP may be used by bootloader. */
        at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
-       clk_disable(udc->iclk);
+       clk_disable_unprepare(udc->iclk);
 
        /* request UDC and maybe VBUS irqs */
        udc->udp_irq = platform_get_irq(pdev, 0);
index 5d3561ea1c1595ea30f07bc3ad35253647701d97..edab45da37417e16960b75033a46a8453475b77b 100644 (file)
@@ -959,8 +959,11 @@ static struct usb_function_instance *ecm_alloc_inst(void)
        mutex_init(&opts->lock);
        opts->func_inst.free_func_inst = ecm_free_inst;
        opts->net = gether_setup_default();
-       if (IS_ERR(opts->net))
-               return ERR_PTR(PTR_ERR(opts->net));
+       if (IS_ERR(opts->net)) {
+               struct net_device *net = opts->net;
+               kfree(opts);
+               return ERR_CAST(net);
+       }
 
        config_group_init_type_name(&opts->func_inst.group, "", &ecm_func_type);
 
index 90ee8022e8d80c29fbff9a1298d62c13ec869b42..d00392d879db3aa3e75d093d4e26041fa42bcb54 100644 (file)
@@ -593,8 +593,11 @@ static struct usb_function_instance *eem_alloc_inst(void)
        mutex_init(&opts->lock);
        opts->func_inst.free_func_inst = eem_free_inst;
        opts->net = gether_setup_default();
-       if (IS_ERR(opts->net))
-               return ERR_CAST(opts->net);
+       if (IS_ERR(opts->net)) {
+               struct net_device *net = opts->net;
+               kfree(opts);
+               return ERR_CAST(net);
+       }
 
        config_group_init_type_name(&opts->func_inst.group, "", &eem_func_type);
 
index 952177f7eb9b40e8045bfa85730239ab22efd97c..1c28fe13328a13935a3976ecc409cba113a81221 100644 (file)
@@ -1350,8 +1350,11 @@ static struct usb_function_instance *ncm_alloc_inst(void)
        mutex_init(&opts->lock);
        opts->func_inst.free_func_inst = ncm_free_inst;
        opts->net = gether_setup_default();
-       if (IS_ERR(opts->net))
-               return ERR_PTR(PTR_ERR(opts->net));
+       if (IS_ERR(opts->net)) {
+               struct net_device *net = opts->net;
+               kfree(opts);
+               return ERR_CAST(net);
+       }
 
        config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type);
 
index 7944fb0efe3b6a67471e7379a03a5d8ebc9b23fb..1bf26e9f38cd3c4573331ff77d6a9caa55a0be7e 100644 (file)
@@ -656,8 +656,11 @@ static struct usb_function_instance *phonet_alloc_inst(void)
 
        opts->func_inst.free_func_inst = phonet_free_inst;
        opts->net = gphonet_setup_default();
-       if (IS_ERR(opts->net))
-               return ERR_PTR(PTR_ERR(opts->net));
+       if (IS_ERR(opts->net)) {
+               struct net_device *net = opts->net;
+               kfree(opts);
+               return ERR_CAST(net);
+       }
 
        config_group_init_type_name(&opts->func_inst.group, "",
                        &phonet_func_type);
index 191df35ae69d04e31c6fc70ac7d76f2b4ff83be3..717ed7f956395412bf5d6da1d605921c71b82532 100644 (file)
@@ -963,8 +963,11 @@ static struct usb_function_instance *rndis_alloc_inst(void)
        mutex_init(&opts->lock);
        opts->func_inst.free_func_inst = rndis_free_inst;
        opts->net = gether_setup_default();
-       if (IS_ERR(opts->net))
-               return ERR_CAST(opts->net);
+       if (IS_ERR(opts->net)) {
+               struct net_device *net = opts->net;
+               kfree(opts);
+               return ERR_CAST(net);
+       }
 
        config_group_init_type_name(&opts->func_inst.group, "",
                                    &rndis_func_type);
index 5601e1d96c4fabd7f8a44bc80703080495fba56a..7c8674fa7e8094074aa794fe9407e2adeab7548a 100644 (file)
@@ -505,8 +505,11 @@ static struct usb_function_instance *geth_alloc_inst(void)
        mutex_init(&opts->lock);
        opts->func_inst.free_func_inst = geth_free_inst;
        opts->net = gether_setup_default();
-       if (IS_ERR(opts->net))
-               return ERR_CAST(opts->net);
+       if (IS_ERR(opts->net)) {
+               struct net_device *net = opts->net;
+               kfree(opts);
+               return ERR_CAST(net);
+       }
 
        config_group_init_type_name(&opts->func_inst.group, "",
                                    &gether_func_type);
index cce5535b1dc6744f86a2a3c88d35c756ef4335cd..10cd18ddd0d40207f2d33bd94e41dff040c842f2 100644 (file)
@@ -1074,7 +1074,7 @@ static struct usb_gadget_ops fotg210_gadget_ops = {
        .udc_stop               = fotg210_udc_stop,
 };
 
-static int __exit fotg210_udc_remove(struct platform_device *pdev)
+static int fotg210_udc_remove(struct platform_device *pdev)
 {
        struct fotg210_udc *fotg210 = dev_get_drvdata(&pdev->dev);
 
@@ -1088,7 +1088,7 @@ static int __exit fotg210_udc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __init fotg210_udc_probe(struct platform_device *pdev)
+static int fotg210_udc_probe(struct platform_device *pdev)
 {
        struct resource *res, *ires;
        struct fotg210_udc *fotg210 = NULL;
index 07fdb3eaf48a4fd1be386e346e6e9fccc53e78ce..ec6a2d2903988ffb7a23aa12b63b0f95fd4f601a 100644 (file)
@@ -1776,7 +1776,7 @@ static int mv_u3d_remove(struct platform_device *dev)
        kfree(u3d->eps);
 
        if (u3d->irq)
-               free_irq(u3d->irq, &dev->dev);
+               free_irq(u3d->irq, u3d);
 
        if (u3d->cap_regs)
                iounmap(u3d->cap_regs);
@@ -1974,7 +1974,7 @@ static int mv_u3d_probe(struct platform_device *dev)
        return 0;
 
 err_unregister:
-       free_irq(u3d->irq, &dev->dev);
+       free_irq(u3d->irq, u3d);
 err_request_irq:
 err_get_irq:
        kfree(u3d->status_req);
index ffd8fa5411015f823bc5701777e20cd928848f56..c28ac9872030ab1487a4dd74ffb5ee54af950d67 100644 (file)
@@ -50,6 +50,8 @@ static DEFINE_MUTEX(udc_lock);
 
 /* ------------------------------------------------------------------------- */
 
+#ifdef CONFIG_HAS_DMA
+
 int usb_gadget_map_request(struct usb_gadget *gadget,
                struct usb_request *req, int is_in)
 {
@@ -99,6 +101,8 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
+#endif /* CONFIG_HAS_DMA */
+
 /* ------------------------------------------------------------------------- */
 
 void usb_gadget_set_state(struct usb_gadget *gadget,
@@ -194,9 +198,11 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
        dev_set_name(&gadget->dev, "gadget");
        gadget->dev.parent = parent;
 
+#ifdef CONFIG_HAS_DMA
        dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
        gadget->dev.dma_parms = parent->dma_parms;
        gadget->dev.dma_mask = parent->dma_mask;
+#endif
 
        if (release)
                gadget->dev.release = release;
index 2b702772d04d3353cc570c340f04c9701fa11210..6dce37555c4f6303b5efa657af88096db2b2140e 100644 (file)
@@ -874,6 +874,7 @@ static int ehci_hub_control (
                                ehci->reset_done[wIndex] = jiffies
                                                + msecs_to_jiffies(20);
                                usb_hcd_start_port_resume(&hcd->self, wIndex);
+                               set_bit(wIndex, &ehci->resuming_ports);
                                /* check the port again */
                                mod_timer(&ehci_to_hcd(ehci)->rh_timer,
                                                ehci->reset_done[wIndex]);
index 4b8a2092432f8911b5d73053e34b135041fd0e4d..978c849f9c9a1ef9631d86fa80ccea93371f61ea 100644 (file)
@@ -13,6 +13,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
 void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
 void sb800_prefetch(struct device *dev, int on);
 #else
+struct pci_dev;
 static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
 static inline void usb_amd_dev_put(void) {}
index cc24e39b97d5b8b2bdf7faada7f7767b4f8013c2..f00cb203faea569b2e87e79e8371455a7abd77b4 100644 (file)
@@ -93,7 +93,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                        pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
-               xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
                xhci->quirks |= XHCI_EP_LIMIT_QUIRK;
                xhci->limit_active_eps = 64;
                xhci->quirks |= XHCI_SW_BW_CHECKING;
index 1e57eafa69101aaee797b7890020c66865ef4c16..5b08cd85f8e7fe9646228da946166dfb188c10d2 100644 (file)
@@ -434,7 +434,7 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
 
        /* A ring has pending URBs if its TD list is not empty */
        if (!(ep->ep_state & EP_HAS_STREAMS)) {
-               if (!(list_empty(&ep->ring->td_list)))
+               if (ep->ring && !(list_empty(&ep->ring->td_list)))
                        xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0);
                return;
        }
index 2c49f00260ca2ad9cd0e79bb3078dbd25bb864d6..41eb4fc33453525422b95218b6d51b34aaa617b5 100644 (file)
@@ -329,7 +329,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
        return;
 }
 
-static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
+static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci)
 {
        int i;
 
@@ -1181,9 +1181,6 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
        }
 
        xhci = hcd_to_xhci(hcd);
-       if (xhci->xhc_state & XHCI_STATE_HALTED)
-               return -ENODEV;
-
        if (check_virt_dev) {
                if (!udev->slot_id || !xhci->devs[udev->slot_id]) {
                        printk(KERN_DEBUG "xHCI %s called with unaddressed "
@@ -1199,6 +1196,9 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
                }
        }
 
+       if (xhci->xhc_state & XHCI_STATE_HALTED)
+               return -ENODEV;
+
        return 1;
 }
 
@@ -3898,7 +3898,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
  * Issue an Evaluate Context command to change the Maximum Exit Latency in the
  * slot context.  If that succeeds, store the new MEL in the xhci_virt_device.
  */
-static int xhci_change_max_exit_latency(struct xhci_hcd *xhci,
+static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
                        struct usb_device *udev, u16 max_exit_latency)
 {
        struct xhci_virt_device *virt_dev;
@@ -4892,6 +4892,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
 
        get_quirks(dev, xhci);
 
+       /* In xhci controllers which follow xhci 1.0 spec gives a spurious
+        * success event after a short transfer. This quirk will ignore such
+        * spurious event.
+        */
+       if (xhci->hci_version > 0x96)
+               xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
+
        /* Make sure the HC is halted. */
        retval = xhci_halt(xhci);
        if (retval)
index c21386ec5d35d142b7d0d84abe2e3f3cb5be7125..de98906f786d08ebac625b3cc8213de5d79cf68e 100644 (file)
@@ -3247,6 +3247,7 @@ static const struct usb_device_id sisusb_table[] = {
        { USB_DEVICE(0x0711, 0x0903) },
        { USB_DEVICE(0x0711, 0x0918) },
        { USB_DEVICE(0x0711, 0x0920) },
+       { USB_DEVICE(0x0711, 0x0950) },
        { USB_DEVICE(0x182d, 0x021c) },
        { USB_DEVICE(0x182d, 0x0269) },
        { }
index efe6e1464f45b59fb831a9ca5c05361593b3b7a5..a2fb30bbb971c41f76fc8ad1eb358449f0117657 100644 (file)
@@ -71,9 +71,9 @@ static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = {
        {1250, 5, 4, 20, 0},            /* 12 MHz */
        {3125, 20, 4, 20, 0},           /* 16.8 MHz */
        {1172, 8, 4, 20, 65537},        /* 19.2 MHz */
+       {1000, 7, 4, 10, 0},            /* 20 MHz */
        {1250, 12, 4, 20, 0},           /* 26 MHz */
        {3125, 47, 4, 20, 92843},       /* 38.4 MHz */
-       {1000, 7, 4, 10, 0},            /* 20 MHz */
 
 };
 
index 1011c16ade7e4b2de81db46d0ab8ddfc599b24bc..758b86d0fcb386af39561d2d25e8ad9983c97fbf 100644 (file)
@@ -388,7 +388,7 @@ static int samsung_usb2phy_probe(struct platform_device *pdev)
                clk = devm_clk_get(dev, "otg");
 
        if (IS_ERR(clk)) {
-               dev_err(dev, "Failed to get otg clock\n");
+               dev_err(dev, "Failed to get usbhost/otg clock\n");
                return PTR_ERR(clk);
        }
 
index ed4949faa70d14502a6669a3fb35b6fb814b35c6..805940c373532bd4d548b5cf4d868ce4d75024ad 100644 (file)
@@ -855,10 +855,6 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget,
        struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
        struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 
-       if (!driver             ||
-           !driver->unbind)
-               return -EINVAL;
-
        usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
        gpriv->driver = NULL;
 
index d6ef2f8da37dca2f7206f26db7d6269bdf0d13e6..0eae4ba3760ed87f633b0d449a833f1e5109107d 100644 (file)
@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
        { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
+       { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
        { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
        { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
        { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
@@ -118,6 +119,8 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
        { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
        { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+       { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
+       { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
@@ -148,6 +151,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
        { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
+       { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
        { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
        { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
index 0a818b238508e26ab4b1932a844b740ba25c5d3c..603fb70dde8005ddfcf9743e2f3f8d0acd616bb5 100644 (file)
@@ -905,20 +905,20 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Reading Spreg failed\n");
-               return -1;
+               goto err;
        }
        Data |= 0x80;
        status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "writing Spreg failed\n");
-               return -1;
+               goto err;
        }
 
        Data &= ~0x80;
        status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "writing Spreg failed\n");
-               return -1;
+               goto err;
        }
        /* End of block to be checked */
 
@@ -927,7 +927,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
                                                                        &Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Reading Controlreg failed\n");
-               return -1;
+               goto err;
        }
        Data |= 0x08;           /* Driver done bit */
        Data |= 0x20;           /* rx_disable */
@@ -935,7 +935,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
                                mos7840_port->ControlRegOffset, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "writing Controlreg failed\n");
-               return -1;
+               goto err;
        }
        /* do register settings here */
        /* Set all regs to the device default values. */
@@ -946,21 +946,21 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "disabling interrupts failed\n");
-               return -1;
+               goto err;
        }
        /* Set FIFO_CONTROL_REGISTER to the default value */
        Data = 0x00;
        status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER  failed\n");
-               return -1;
+               goto err;
        }
 
        Data = 0xcf;
        status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
        if (status < 0) {
                dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER  failed\n");
-               return -1;
+               goto err;
        }
 
        Data = 0x03;
@@ -1103,6 +1103,15 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* mos7840_change_port_settings(mos7840_port,old_termios); */
 
        return 0;
+err:
+       for (j = 0; j < NUM_URBS; ++j) {
+               urb = mos7840_port->write_urb_pool[j];
+               if (!urb)
+                       continue;
+               kfree(urb->transfer_buffer);
+               usb_free_urb(urb);
+       }
+       return status;
 }
 
 /*****************************************************************************
index 5dd857de05b04f5ecf4cefe7a370e6013db67118..1cf6f125f5f078624b41bd1256686d35f28ee4b7 100644 (file)
@@ -341,17 +341,12 @@ static void option_instat_callback(struct urb *urb);
 #define OLIVETTI_VENDOR_ID                     0x0b3c
 #define OLIVETTI_PRODUCT_OLICARD100            0xc000
 #define OLIVETTI_PRODUCT_OLICARD145            0xc003
+#define OLIVETTI_PRODUCT_OLICARD200            0xc005
 
 /* Celot products */
 #define CELOT_VENDOR_ID                                0x211f
 #define CELOT_PRODUCT_CT680M                   0x6801
 
-/* ONDA Communication vendor id */
-#define ONDA_VENDOR_ID       0x1ee8
-
-/* ONDA MT825UP HSDPA 14.2 modem */
-#define ONDA_MT825UP         0x000b
-
 /* Samsung products */
 #define SAMSUNG_VENDOR_ID                       0x04e8
 #define SAMSUNG_PRODUCT_GT_B3730                0x6889
@@ -444,7 +439,8 @@ static void option_instat_callback(struct urb *urb);
 
 /* Hyundai Petatel Inc. products */
 #define PETATEL_VENDOR_ID                      0x1ff4
-#define PETATEL_PRODUCT_NP10T                  0x600e
+#define PETATEL_PRODUCT_NP10T_600A             0x600a
+#define PETATEL_PRODUCT_NP10T_600E             0x600e
 
 /* TP-LINK Incorporated products */
 #define TPLINK_VENDOR_ID                       0x2357
@@ -782,6 +778,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
@@ -817,7 +814,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
@@ -1256,8 +1254,8 @@ static const struct usb_device_id option_ids[] = {
 
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
+       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
-       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) },
@@ -1329,9 +1327,12 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
        { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
        { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
-       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
+       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) },
+       { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) },
        { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000),                                 /* TP-Link MA260 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },    /* D-Link DWM-156 (variant) */
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },    /* D-Link DWM-156 (variant) */
@@ -1339,6 +1340,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 7182bb774b7958f70f50efb823b084c5ea9284d5..375b5a400b6fb8a63b0aaa83272299a15aef6e83 100644 (file)
@@ -371,7 +371,7 @@ static int ti_startup(struct usb_serial *serial)
        usb_set_serial_data(serial, tdev);
 
        /* determine device type */
-       if (usb_match_id(serial->interface, ti_id_table_3410))
+       if (serial->type == &ti_1port_device)
                tdev->td_is_3410 = 1;
        dev_dbg(&dev->dev, "%s - device type is %s\n", __func__,
                tdev->td_is_3410 ? "3410" : "5052");
index 1799335288bd5e60522a60def1c311f07df62286..c015f2c16729c5b4030fc829fae9a3cfb90acde6 100644 (file)
@@ -665,6 +665,13 @@ UNUSUAL_DEV(  0x054c, 0x016a, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_FIX_INQUIRY ),
 
+/* Submitted by Ren Bigcren <bigcren.ren@sonymobile.com> */
+UNUSUAL_DEV(  0x054c, 0x02a5, 0x0100, 0x0100,
+               "Sony Corp.",
+               "MicroVault Flash Drive",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_READ_CAPACITY_16 ),
+
 /* floppy reports multiple luns */
 UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
                "SAMSUNG",
index 5ca11b066b7e51b31e346759fed356e98bfe0d12..886e797f75f9e7b0c6571f2f8ba0ec0b561f0d83 100644 (file)
@@ -101,33 +101,37 @@ static const struct backlight_ops max8925_backlight_ops = {
        .get_brightness = max8925_backlight_get_brightness,
 };
 
-#ifdef CONFIG_OF
-static int max8925_backlight_dt_init(struct platform_device *pdev,
-                             struct max8925_backlight_pdata *pdata)
+static void max8925_backlight_dt_init(struct platform_device *pdev)
 {
        struct device_node *nproot = pdev->dev.parent->of_node, *np;
-       int dual_string;
+       struct max8925_backlight_pdata *pdata;
+       u32 val;
+
+       if (!nproot || !IS_ENABLED(CONFIG_OF))
+               return;
+
+       pdata = devm_kzalloc(&pdev->dev,
+                            sizeof(struct max8925_backlight_pdata),
+                            GFP_KERNEL);
+       if (!pdata)
+               return;
 
-       if (!nproot)
-               return -ENODEV;
        np = of_find_node_by_name(nproot, "backlight");
        if (!np) {
                dev_err(&pdev->dev, "failed to find backlight node\n");
-               return -ENODEV;
+               return;
        }
 
-       of_property_read_u32(np, "maxim,max8925-dual-string", &dual_string);
-       pdata->dual_string = dual_string;
-       return 0;
+       if (!of_property_read_u32(np, "maxim,max8925-dual-string", &val))
+               pdata->dual_string = val;
+
+       pdev->dev.platform_data = pdata;
 }
-#else
-#define max8925_backlight_dt_init(x, y)        (-1)
-#endif
 
 static int max8925_backlight_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
+       struct max8925_backlight_pdata *pdata;
        struct max8925_backlight_data *data;
        struct backlight_device *bl;
        struct backlight_properties props;
@@ -170,13 +174,10 @@ static int max8925_backlight_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, bl);
 
        value = 0;
-       if (pdev->dev.parent->of_node && !pdata) {
-               pdata = devm_kzalloc(&pdev->dev,
-                                    sizeof(struct max8925_backlight_pdata),
-                                    GFP_KERNEL);
-               max8925_backlight_dt_init(pdev, pdata);
-       }
+       if (!pdev->dev.platform_data)
+               max8925_backlight_dt_init(pdev);
 
+       pdata = pdev->dev.platform_data;
        if (pdata) {
                if (pdata->lxw_scl)
                        value |= (1 << 7);
index 8ff6a0019b0b9cc6016da02c3210ae6840a20dfa..c827acb0e943bdab08fd077e56228b170a6a9549 100644 (file)
@@ -830,9 +830,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                        flags = O_WRONLY|O_LARGEFILE;
        }
        *filp = dentry_open(&path, flags, current_cred());
-       if (IS_ERR(*filp))
+       if (IS_ERR(*filp)) {
                host_err = PTR_ERR(*filp);
-       else {
+               *filp = NULL;
+       } else {
                host_err = ima_file_check(*filp, may_flags);
 
                if (may_flags & NFSD_MAY_64BIT_COOKIE)
index 07d735a80a0f777c342c4323ba9393556afe182b..e5869b50dc41acd1788123e0cd49ea2670101e3f 100644 (file)
@@ -39,6 +39,9 @@ typedef struct xfs_timestamp {
  * There is a very similar struct icdinode in xfs_inode which matches the
  * layout of the first 96 bytes of this structure, but is kept in native
  * format instead of big endian.
+ *
+ * Note: di_flushiter is only used by v1/2 inodes - it's effectively a zeroed
+ * padding field for v3 inodes.
  */
 typedef struct xfs_dinode {
        __be16          di_magic;       /* inode magic # = XFS_DINODE_MAGIC */
index b78481f99d9d6a683f0d18815432fce69d8d2838..bb262c25c8de463276e9282d64b299c975eceb7b 100644 (file)
@@ -896,7 +896,6 @@ xfs_dinode_to_disk(
        to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
        to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
        memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
-       to->di_flushiter = cpu_to_be16(from->di_flushiter);
        to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
        to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
        to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
@@ -924,6 +923,9 @@ xfs_dinode_to_disk(
                to->di_lsn = cpu_to_be64(from->di_lsn);
                memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2));
                uuid_copy(&to->di_uuid, &from->di_uuid);
+               to->di_flushiter = 0;
+       } else {
+               to->di_flushiter = cpu_to_be16(from->di_flushiter);
        }
 }
 
@@ -1029,10 +1031,14 @@ xfs_dinode_calc_crc(
 /*
  * Read the disk inode attributes into the in-core inode structure.
  *
- * If we are initialising a new inode and we are not utilising the
- * XFS_MOUNT_IKEEP inode cluster mode, we can simple build the new inode core
- * with a random generation number. If we are keeping inodes around, we need to
- * read the inode cluster to get the existing generation number off disk.
+ * For version 5 superblocks, if we are initialising a new inode and we are not
+ * utilising the XFS_MOUNT_IKEEP inode cluster mode, we can simple build the new
+ * inode core with a random generation number. If we are keeping inodes around,
+ * we need to read the inode cluster to get the existing generation number off
+ * disk. Further, if we are using version 4 superblocks (i.e. v1/v2 inode
+ * format) then log recovery is dependent on the di_flushiter field being
+ * initialised from the current on-disk value and hence we must also read the
+ * inode off disk.
  */
 int
 xfs_iread(
@@ -1054,6 +1060,7 @@ xfs_iread(
 
        /* shortcut IO on inode allocation if possible */
        if ((iget_flags & XFS_IGET_CREATE) &&
+           xfs_sb_version_hascrc(&mp->m_sb) &&
            !(mp->m_flags & XFS_MOUNT_IKEEP)) {
                /* initialise the on-disk inode core */
                memset(&ip->i_d, 0, sizeof(ip->i_d));
@@ -2882,12 +2889,18 @@ xfs_iflush_int(
                        __func__, ip->i_ino, ip->i_d.di_forkoff, ip);
                goto corrupt_out;
        }
+
        /*
-        * bump the flush iteration count, used to detect flushes which
-        * postdate a log record during recovery. This is redundant as we now
-        * log every change and hence this can't happen. Still, it doesn't hurt.
+        * Inode item log recovery for v1/v2 inodes are dependent on the
+        * di_flushiter count for correct sequencing. We bump the flush
+        * iteration count so we can detect flushes which postdate a log record
+        * during recovery. This is redundant as we now log every change and
+        * hence this can't happen but we need to still do it to ensure
+        * backwards compatibility with old kernels that predate logging all
+        * inode changes.
         */
-       ip->i_d.di_flushiter++;
+       if (ip->i_d.di_version < 3)
+               ip->i_d.di_flushiter++;
 
        /*
         * Copy the dirty parts of the inode into the on-disk
index 6fcc910a50b9d7e3fbd3c15851aa0ee0cfc1b6af..7681b19aa5dc565a9807005ff3f1d6428a22f016 100644 (file)
@@ -2592,8 +2592,16 @@ xlog_recover_inode_pass2(
                goto error;
        }
 
-       /* Skip replay when the on disk inode is newer than the log one */
-       if (dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
+       /*
+        * di_flushiter is only valid for v1/2 inodes. All changes for v3 inodes
+        * are transactional and if ordering is necessary we can determine that
+        * more accurately by the LSN field in the V3 inode core. Don't trust
+        * the inode versions we might be changing them here - use the
+        * superblock flag to determine whether we need to look at di_flushiter
+        * to skip replay when the on disk inode is newer than the log one
+        */
+       if (!xfs_sb_version_hascrc(&mp->m_sb) &&
+           dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
                /*
                 * Deal with the wrap case, DI_MAX_FLUSH is less
                 * than smaller numbers
@@ -2608,6 +2616,7 @@ xlog_recover_inode_pass2(
                        goto error;
                }
        }
+
        /* Take the opportunity to reset the flush iteration count */
        dicp->di_flushiter = 0;
 
index b26dc4fb7ba8283f22b0d8f646a58a06fd00d510..61109f2609fc3ee446ec43e242875b28ae719344 100644 (file)
@@ -17,21 +17,12 @@ struct acpi_device;
 #define ACPI_VIDEO_DISPLAY_LEGACY_TV      0x0200
 
 #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
-extern int __acpi_video_register(bool backlight_quirks);
-static inline int acpi_video_register(void)
-{
-       return __acpi_video_register(false);
-}
-static inline int acpi_video_register_with_quirks(void)
-{
-       return __acpi_video_register(true);
-}
+extern int acpi_video_register(void);
 extern void acpi_video_unregister(void);
 extern int acpi_video_get_edid(struct acpi_device *device, int type,
                               int device_id, void **edid);
 #else
 static inline int acpi_video_register(void) { return 0; }
-static inline int acpi_video_register_with_quirks(void) { return 0; }
 static inline void acpi_video_unregister(void) { return; }
 static inline int acpi_video_get_edid(struct acpi_device *device, int type,
                                      int device_id, void **edid)
index 15e997fa78f24d9822defea3d2eb097b088580e7..4aa2b48cd15183e457a3eb96288dca81039cef37 100644 (file)
 #define VF610_CLK_GPU_SEL              145
 #define VF610_CLK_GPU_EN               146
 #define VF610_CLK_GPU2D                        147
-#define VF610_CLK_END                  148
+#define VF610_CLK_ENET0                        148
+#define VF610_CLK_ENET1                        149
+#define VF610_CLK_END                  150
 
 #endif /* __DT_BINDINGS_CLOCK_VF610_H */
index 469e0325e6f4b409fb07168da7b9adb1ddce5915..2fbc804e1a45cea943c9241309601f941abd5d14 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef _DT_BINDINGS_PINCTRL_AM33XX_H
 #define _DT_BINDINGS_PINCTRL_AM33XX_H
 
-#include <include/dt-bindings/pinctrl/omap.h>
+#include <dt-bindings/pinctrl/omap.h>
 
 /* am33xx specific mux bit defines */
 #undef PULL_ENA
index 6ad72f92469c556368742f7c2d3301acfcfd5a0c..353ba256f3681e4f6ddd8b18b9feba61b1d98cec 100644 (file)
@@ -191,7 +191,6 @@ extern bool wmi_has_guid(const char *guid);
 #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO                 0x0200
 #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR         0x0400
 #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO          0x0800
-#define ACPI_VIDEO_SKIP_BACKLIGHT                      0x1000
 
 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
 
index 297462b9f41acb7c95607daa36516b017e37be53..e9ac882868c0353f8f6bb7f2baba2a73c8602c41 100644 (file)
@@ -542,8 +542,7 @@ int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
 
 int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen);
-int task_cgroup_path_from_hierarchy(struct task_struct *task, int hierarchy_id,
-                                   char *buf, size_t buflen);
+int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
 
 int cgroup_task_count(const struct cgroup *cgrp);
 
index 6e7ec64b69ab4b7aa5ee7aacef569f633f0de296..b613ffd402d1bdd38747e45e26260b28a4355768 100644 (file)
@@ -1,86 +1,55 @@
-/* Add subsystem definitions of the form SUBSYS(<name>) in this
- * file. Surround each one by a line of comment markers so that
- * patches don't collide
+/*
+ * List of cgroup subsystems.
+ *
+ * DO NOT ADD ANY SUBSYSTEM WITHOUT EXPLICIT ACKS FROM CGROUP MAINTAINERS.
  */
-
-/* */
-
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CPUSETS)
 SUBSYS(cpuset)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEBUG)
 SUBSYS(debug)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_SCHED)
 SUBSYS(cpu_cgroup)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_CPUACCT)
 SUBSYS(cpuacct)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_MEMCG)
 SUBSYS(mem_cgroup)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEVICE)
 SUBSYS(devices)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_FREEZER)
 SUBSYS(freezer)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_NET_CLS_CGROUP)
 SUBSYS(net_cls)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_BLK_CGROUP)
 SUBSYS(blkio)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_PERF)
 SUBSYS(perf)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_NETPRIO_CGROUP)
 SUBSYS(net_prio)
 #endif
 
-/* */
-
 #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_HUGETLB)
 SUBSYS(hugetlb)
 #endif
-
-/* */
-
-#ifdef CONFIG_CGROUP_BCACHE
-SUBSYS(bcache)
-#endif
-
-/* */
+/*
+ * DO NOT ADD ANY SUBSYSTEM WITHOUT EXPLICIT ACKS FROM CGROUP MAINTAINERS.
+ */
index b3cb71f0d3b0d19b8c08e70348dee1bb5e5ba6ad..a9c96d865ee7144b577afc3752c0a1a94cd95e11 100644 (file)
@@ -3,10 +3,6 @@
 
 #include <linux/types.h>
 
-#define CRC_T10DIF_DIGEST_SIZE 2
-#define CRC_T10DIF_BLOCK_SIZE 1
-
-__u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, size_t len);
 __u16 crc_t10dif(unsigned char const *, size_t);
 
 #endif
index 0b763276f6199a255d304b572e0c414c90252056..5c6d7fbaf89e00dbed2d9cc418318980f7de3d2b 100644 (file)
@@ -622,7 +622,7 @@ struct edac_raw_error_desc {
  */
 struct mem_ctl_info {
        struct device                   dev;
-       struct bus_type                 bus;
+       struct bus_type                 *bus;
 
        struct list_head link;  /* for global list of mem_ctl_info structs */
 
@@ -742,4 +742,9 @@ struct mem_ctl_info {
 #endif
 };
 
+/*
+ * Maximum number of memory controllers in the coherent fabric.
+ */
+#define EDAC_MAX_MCS   16
+
 #endif
index dab34a1deb2c156ecdb8a67328d6cfbb6b0d5c8d..b6bdcd66c07d2e758ba677f9c9c1796ada542bc8 100644 (file)
 #define IMX6Q_GPR1_EXC_MON_MASK                        BIT(22)
 #define IMX6Q_GPR1_EXC_MON_OKAY                        0x0
 #define IMX6Q_GPR1_EXC_MON_SLVE                        BIT(22)
-#define IMX6Q_GPR1_MIPI_IPU2_SEL_MASK          BIT(21)
-#define IMX6Q_GPR1_MIPI_IPU2_SEL_GASKET                0x0
-#define IMX6Q_GPR1_MIPI_IPU2_SEL_IOMUX         BIT(21)
-#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK          BIT(20)
-#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET                0x0
-#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX         BIT(20)
-#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK          BIT(19)
+#define IMX6Q_GPR1_ENET_CLK_SEL_MASK           BIT(21)
+#define IMX6Q_GPR1_ENET_CLK_SEL_PAD            0
+#define IMX6Q_GPR1_ENET_CLK_SEL_ANATOP         BIT(21)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK          BIT(20)
 #define IMX6Q_GPR1_MIPI_IPU2_MUX_GASKET                0x0
-#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX         BIT(19)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX         BIT(20)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK          BIT(19)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET                0x0
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX         BIT(19)
 #define IMX6Q_GPR1_PCIE_TEST_PD                        BIT(18)
 #define IMX6Q_GPR1_IPU_VPU_MUX_MASK            BIT(17)
 #define IMX6Q_GPR1_IPU_VPU_MUX_IPU1            0x0
 #define IMX6Q_GPR13_CAN2_STOP_REQ              BIT(29)
 #define IMX6Q_GPR13_CAN1_STOP_REQ              BIT(28)
 #define IMX6Q_GPR13_ENET_STOP_REQ              BIT(27)
-#define IMX6Q_GPR13_SATA_PHY_8_MASK            (0x7 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_0_5_DB          (0x0 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_1_0_DB          (0x1 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_1_5_DB          (0x2 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_2_0_DB          (0x3 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_2_5_DB          (0x4 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_3_0_DB          (0x5 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_3_5_DB          (0x6 << 24)
-#define IMX6Q_GPR13_SATA_PHY_8_4_0_DB          (0x7 << 24)
-#define IMX6Q_GPR13_SATA_PHY_7_MASK            (0x1f << 19)
-#define IMX6Q_GPR13_SATA_PHY_7_SATA1I          (0x10 << 19)
-#define IMX6Q_GPR13_SATA_PHY_7_SATA1M          (0x10 << 19)
-#define IMX6Q_GPR13_SATA_PHY_7_SATA1X          (0x1a << 19)
-#define IMX6Q_GPR13_SATA_PHY_7_SATA2I          (0x12 << 19)
-#define IMX6Q_GPR13_SATA_PHY_7_SATA2M          (0x12 << 19)
-#define IMX6Q_GPR13_SATA_PHY_7_SATA2X          (0x1a << 19)
-#define IMX6Q_GPR13_SATA_PHY_6_MASK            (0x7 << 16)
-#define IMX6Q_GPR13_SATA_SPEED_MASK            BIT(15)
-#define IMX6Q_GPR13_SATA_SPEED_1P5G            0x0
-#define IMX6Q_GPR13_SATA_SPEED_3P0G            BIT(15)
-#define IMX6Q_GPR13_SATA_PHY_5                 BIT(14)
-#define IMX6Q_GPR13_SATA_PHY_4_MASK            (0x7 << 11)
-#define IMX6Q_GPR13_SATA_PHY_4_16_16           (0x0 << 11)
-#define IMX6Q_GPR13_SATA_PHY_4_14_16           (0x1 << 11)
-#define IMX6Q_GPR13_SATA_PHY_4_12_16           (0x2 << 11)
-#define IMX6Q_GPR13_SATA_PHY_4_10_16           (0x3 << 11)
-#define IMX6Q_GPR13_SATA_PHY_4_9_16            (0x4 << 11)
-#define IMX6Q_GPR13_SATA_PHY_4_8_16            (0x5 << 11)
-#define IMX6Q_GPR13_SATA_PHY_3_MASK            (0xf << 7)
-#define IMX6Q_GPR13_SATA_PHY_3_OFF             0x7
-#define IMX6Q_GPR13_SATA_PHY_2_MASK            (0x1f << 2)
-#define IMX6Q_GPR13_SATA_PHY_2_OFF             0x2
-#define IMX6Q_GPR13_SATA_PHY_1_MASK            (0x3 << 0)
-#define IMX6Q_GPR13_SATA_PHY_1_FAST            (0x0 << 0)
-#define IMX6Q_GPR13_SATA_PHY_1_MED             (0x1 << 0)
-#define IMX6Q_GPR13_SATA_PHY_1_SLOW            (0x2 << 0)
-
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK                (0x7 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB      (0x0 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB      (0x1 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB      (0x2 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB      (0x3 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB      (0x4 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB      (0x5 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB      (0x6 << 24)
+#define IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB      (0x7 << 24)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK       (0x1f << 19)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA1I     (0x10 << 19)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA1M     (0x10 << 19)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA1X     (0x1a << 19)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2I     (0x12 << 19)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M     (0x12 << 19)
+#define IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2X     (0x1a << 19)
+#define IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK     (0x7 << 16)
+#define IMX6Q_GPR13_SATA_RX_DPLL_MODE_1P_1F    (0x0 << 16)
+#define IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_2F    (0x1 << 16)
+#define IMX6Q_GPR13_SATA_RX_DPLL_MODE_1P_4F    (0x2 << 16)
+#define IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F    (0x3 << 16)
+#define IMX6Q_GPR13_SATA_SPD_MODE_MASK         BIT(15)
+#define IMX6Q_GPR13_SATA_SPD_MODE_1P5G         0x0
+#define IMX6Q_GPR13_SATA_SPD_MODE_3P0G         BIT(15)
+#define IMX6Q_GPR13_SATA_MPLL_SS_EN            BIT(14)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_MASK         (0x7 << 11)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_16_16                (0x0 << 11)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_14_16                (0x1 << 11)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_12_16                (0x2 << 11)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_10_16                (0x3 << 11)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_9_16         (0x4 << 11)
+#define IMX6Q_GPR13_SATA_TX_ATTEN_8_16         (0x5 << 11)
+#define IMX6Q_GPR13_SATA_TX_BOOST_MASK         (0xf << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB      (0x0 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB      (0x1 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB      (0x2 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB      (0x3 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB      (0x4 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB      (0x5 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB      (0x6 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB      (0x7 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB      (0x8 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB      (0x9 << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB      (0xa << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB      (0xb << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB      (0xc << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB      (0xd << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB      (0xe << 7)
+#define IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB      (0xf << 7)
+#define IMX6Q_GPR13_SATA_TX_LVL_MASK           (0x1f << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_937_V                (0x00 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_947_V                (0x01 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_957_V                (0x02 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_966_V                (0x03 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_976_V                (0x04 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_986_V                (0x05 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_0_996_V                (0x06 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_005_V                (0x07 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_015_V                (0x08 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_025_V                (0x09 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_035_V                (0x0a << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_045_V                (0x0b << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_054_V                (0x0c << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_064_V                (0x0d << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_074_V                (0x0e << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_084_V                (0x0f << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_094_V                (0x10 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_104_V                (0x11 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_113_V                (0x12 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_123_V                (0x13 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_133_V                (0x14 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_143_V                (0x15 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_152_V                (0x16 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_162_V                (0x17 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_172_V                (0x18 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_182_V                (0x19 << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_191_V                (0x1a << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_201_V                (0x1b << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_211_V                (0x1c << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_221_V                (0x1d << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_230_V                (0x1e << 2)
+#define IMX6Q_GPR13_SATA_TX_LVL_1_240_V                (0x1f << 2)
+#define IMX6Q_GPR13_SATA_MPLL_CLK_EN           BIT(1)
+#define IMX6Q_GPR13_SATA_TX_EDGE_RATE          BIT(0)
 #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
index 9eb515bb799d071bdad4c342fa61b00e32072588..1706b3597ce00c10776d8c8fbf8e0c6067afcb6a 100644 (file)
@@ -12,7 +12,7 @@ struct pxamci_platform_data {
        unsigned long detect_delay_ms;          /* delay in millisecond before detecting cards after interrupt */
        int (*init)(struct device *, irq_handler_t , void *);
        int (*get_ro)(struct device *);
-       void (*setpower)(struct device *, unsigned int);
+       int (*setpower)(struct device *, unsigned int);
        void (*exit)(struct device *, void *);
        int gpio_card_detect;                   /* gpio detecting card insertion */
        int gpio_card_ro;                       /* gpio detecting read only toggle */
index 80587fdbba3ef5adcf116afe9676f9b34543b583..1a2e9901a22eb4d5d14b52b56057b84d4bd19820 100644 (file)
 
 #include <drm/drm_mode.h>
 
+enum rcar_du_output {
+       RCAR_DU_OUTPUT_DPAD0,
+       RCAR_DU_OUTPUT_DPAD1,
+       RCAR_DU_OUTPUT_LVDS0,
+       RCAR_DU_OUTPUT_LVDS1,
+       RCAR_DU_OUTPUT_TCON,
+       RCAR_DU_OUTPUT_MAX,
+};
+
 enum rcar_du_encoder_type {
        RCAR_DU_ENCODER_UNUSED = 0,
+       RCAR_DU_ENCODER_NONE,
        RCAR_DU_ENCODER_VGA,
        RCAR_DU_ENCODER_LVDS,
 };
@@ -28,22 +38,32 @@ struct rcar_du_panel_data {
        struct drm_mode_modeinfo mode;
 };
 
-struct rcar_du_encoder_lvds_data {
+struct rcar_du_connector_lvds_data {
        struct rcar_du_panel_data panel;
 };
 
-struct rcar_du_encoder_vga_data {
+struct rcar_du_connector_vga_data {
        /* TODO: Add DDC information for EDID retrieval */
 };
 
+/*
+ * struct rcar_du_encoder_data - Encoder platform data
+ * @type: the encoder type (RCAR_DU_ENCODER_*)
+ * @output: the DU output the connector is connected to (RCAR_DU_OUTPUT_*)
+ * @connector.lvds: platform data for LVDS connectors
+ * @connector.vga: platform data for VGA connectors
+ *
+ * Encoder platform data describes an on-board encoder, its associated DU SoC
+ * output, and the connector.
+ */
 struct rcar_du_encoder_data {
-       enum rcar_du_encoder_type encoder;
-       unsigned int output;
+       enum rcar_du_encoder_type type;
+       enum rcar_du_output output;
 
        union {
-               struct rcar_du_encoder_lvds_data lvds;
-               struct rcar_du_encoder_vga_data vga;
-       } u;
+               struct rcar_du_connector_lvds_data lvds;
+               struct rcar_du_connector_vga_data vga;
+       } connector;
 };
 
 struct rcar_du_platform_data {
index 382cf710ca9aa11b001d874efa516e229f5b8254..5b1c9848124cb8c366f95a0dbfaa6d54d64d1927 100644 (file)
@@ -124,6 +124,10 @@ void shdma_chan_remove(struct shdma_chan *schan);
 int shdma_init(struct device *dev, struct shdma_dev *sdev,
                    int chan_num);
 void shdma_cleanup(struct shdma_dev *sdev);
+#if IS_ENABLED(CONFIG_SH_DMAE_BASE)
 bool shdma_chan_filter(struct dma_chan *chan, void *arg);
+#else
+#define shdma_chan_filter NULL
+#endif
 
 #endif
index a232b7ece1f63c687a2f50da506c9e70ec33555e..0eec2689b9556bee0c3aae530a3035ccbbe29d2a 100644 (file)
@@ -367,17 +367,6 @@ struct usb_bus {
 
 /* ----------------------------------------------------------------------- */
 
-/* This is arbitrary.
- * From USB 2.0 spec Table 11-13, offset 7, a hub can
- * have up to 255 ports. The most yet reported is 10.
- *
- * Current Wireless USB host hardware (Intel i1480 for example) allows
- * up to 22 devices to connect. Upcoming hardware might raise that
- * limit. Because the arrays need to add a bit for hub status data, we
- * do 31, so plus one evens out to four bytes.
- */
-#define USB_MAXCHILDREN                (31)
-
 struct usb_tt;
 
 enum usb_device_removable {
index 7692dc69ccf7aeeb16ebc682b57d519c56642ba1..331499d597fa86cd941d99d5ad8ab9ec2120cb86 100644 (file)
 
 #include <linux/types.h>       /* __u8 etc */
 
+/* This is arbitrary.
+ * From USB 2.0 spec Table 11-13, offset 7, a hub can
+ * have up to 255 ports. The most yet reported is 10.
+ *
+ * Current Wireless USB host hardware (Intel i1480 for example) allows
+ * up to 22 devices to connect. Upcoming hardware might raise that
+ * limit. Because the arrays need to add a bit for hub status data, we
+ * use 31, so plus one evens out to four bytes.
+ */
+#define USB_MAXCHILDREN                31
+
 /*
  * Hub request types
  */
index 0e0b20b8c5db172e8dc07fe4de10358c19939d60..789ec4683db3b73f83e455891bdb319124215f97 100644 (file)
@@ -1845,36 +1845,43 @@ out:
 EXPORT_SYMBOL_GPL(cgroup_path);
 
 /**
- * task_cgroup_path_from_hierarchy - cgroup path of a task on a hierarchy
+ * task_cgroup_path - cgroup path of a task in the first cgroup hierarchy
  * @task: target task
- * @hierarchy_id: the hierarchy to look up @task's cgroup from
  * @buf: the buffer to write the path into
  * @buflen: the length of the buffer
  *
- * Determine @task's cgroup on the hierarchy specified by @hierarchy_id and
- * copy its path into @buf.  This function grabs cgroup_mutex and shouldn't
- * be used inside locks used by cgroup controller callbacks.
+ * Determine @task's cgroup on the first (the one with the lowest non-zero
+ * hierarchy_id) cgroup hierarchy and copy its path into @buf.  This
+ * function grabs cgroup_mutex and shouldn't be used inside locks used by
+ * cgroup controller callbacks.
+ *
+ * Returns 0 on success, fails with -%ENAMETOOLONG if @buflen is too short.
  */
-int task_cgroup_path_from_hierarchy(struct task_struct *task, int hierarchy_id,
-                                   char *buf, size_t buflen)
+int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
 {
        struct cgroupfs_root *root;
-       struct cgroup *cgrp = NULL;
-       int ret = -ENOENT;
+       struct cgroup *cgrp;
+       int hierarchy_id = 1, ret = 0;
+
+       if (buflen < 2)
+               return -ENAMETOOLONG;
 
        mutex_lock(&cgroup_mutex);
 
-       root = idr_find(&cgroup_hierarchy_idr, hierarchy_id);
+       root = idr_get_next(&cgroup_hierarchy_idr, &hierarchy_id);
+
        if (root) {
                cgrp = task_cgroup_from_root(task, root);
                ret = cgroup_path(cgrp, buf, buflen);
+       } else {
+               /* if no hierarchy exists, everyone is in "/" */
+               memcpy(buf, "/", 2);
        }
 
        mutex_unlock(&cgroup_mutex);
-
        return ret;
 }
-EXPORT_SYMBOL_GPL(task_cgroup_path_from_hierarchy);
+EXPORT_SYMBOL_GPL(task_cgroup_path);
 
 /*
  * Control Group taskset
index 67708f46baaefbd6bca64a34a213c2cc7fda5074..8ce9eefc5bb4f6aae3ffa520152a51eb033adb1e 100644 (file)
@@ -1441,12 +1441,22 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
  * the hashes are freed with call_rcu_sched().
  */
 static int
-ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
 {
        struct ftrace_hash *filter_hash;
        struct ftrace_hash *notrace_hash;
        int ret;
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+       /*
+        * There's a small race when adding ops that the ftrace handler
+        * that wants regs, may be called without them. We can not
+        * allow that handler to be called if regs is NULL.
+        */
+       if (regs == NULL && (ops->flags & FTRACE_OPS_FL_SAVE_REGS))
+               return 0;
+#endif
+
        filter_hash = rcu_dereference_raw_notrace(ops->filter_hash);
        notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash);
 
@@ -4218,7 +4228,7 @@ static inline void ftrace_startup_enable(int command) { }
 # define ftrace_shutdown_sysctl()      do { } while (0)
 
 static inline int
-ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
 {
        return 1;
 }
@@ -4241,7 +4251,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
        do_for_each_ftrace_op(op, ftrace_control_list) {
                if (!(op->flags & FTRACE_OPS_FL_STUB) &&
                    !ftrace_function_local_disabled(op) &&
-                   ftrace_ops_test(op, ip))
+                   ftrace_ops_test(op, ip, regs))
                        op->func(ip, parent_ip, op, regs);
        } while_for_each_ftrace_op(op);
        trace_recursion_clear(TRACE_CONTROL_BIT);
@@ -4274,7 +4284,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
         */
        preempt_disable_notrace();
        do_for_each_ftrace_op(op, ftrace_ops_list) {
-               if (ftrace_ops_test(op, ip))
+               if (ftrace_ops_test(op, ip, regs))
                        op->func(ip, parent_ip, op, regs);
        } while_for_each_ftrace_op(op);
        preempt_enable_notrace();
index 3f2477713acaa9ea17ed54be7e79a4e0794d4c17..882ec1dd15155233f89c8c7bad0d2a6dbf58c45f 100644 (file)
@@ -1224,18 +1224,17 @@ void tracing_reset_current(int cpu)
        tracing_reset(&global_trace.trace_buffer, cpu);
 }
 
+/* Must have trace_types_lock held */
 void tracing_reset_all_online_cpus(void)
 {
        struct trace_array *tr;
 
-       mutex_lock(&trace_types_lock);
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
                tracing_reset_online_cpus(&tr->trace_buffer);
 #ifdef CONFIG_TRACER_MAX_TRACE
                tracing_reset_online_cpus(&tr->max_buffer);
 #endif
        }
-       mutex_unlock(&trace_types_lock);
 }
 
 #define SAVED_CMDLINES 128
@@ -2843,6 +2842,17 @@ static int s_show(struct seq_file *m, void *v)
        return 0;
 }
 
+/*
+ * Should be used after trace_array_get(), trace_types_lock
+ * ensures that i_cdev was already initialized.
+ */
+static inline int tracing_get_cpu(struct inode *inode)
+{
+       if (inode->i_cdev) /* See trace_create_cpu_file() */
+               return (long)inode->i_cdev - 1;
+       return RING_BUFFER_ALL_CPUS;
+}
+
 static const struct seq_operations tracer_seq_ops = {
        .start          = s_start,
        .next           = s_next,
@@ -2851,9 +2861,9 @@ static const struct seq_operations tracer_seq_ops = {
 };
 
 static struct trace_iterator *
-__tracing_open(struct trace_array *tr, struct trace_cpu *tc,
-              struct inode *inode, struct file *file, bool snapshot)
+__tracing_open(struct inode *inode, struct file *file, bool snapshot)
 {
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        int cpu;
 
@@ -2894,8 +2904,8 @@ __tracing_open(struct trace_array *tr, struct trace_cpu *tc,
                iter->trace_buffer = &tr->trace_buffer;
        iter->snapshot = snapshot;
        iter->pos = -1;
+       iter->cpu_file = tracing_get_cpu(inode);
        mutex_init(&iter->mutex);
-       iter->cpu_file = tc->cpu;
 
        /* Notify the tracer early; before we stop tracing. */
        if (iter->trace && iter->trace->open)
@@ -2971,44 +2981,22 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp)
        filp->private_data = inode->i_private;
 
        return 0;
-       
-}
-
-static int tracing_open_generic_tc(struct inode *inode, struct file *filp)
-{
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
-
-       if (tracing_disabled)
-               return -ENODEV;
-
-       if (trace_array_get(tr) < 0)
-               return -ENODEV;
-
-       filp->private_data = inode->i_private;
-
-       return 0;
-       
 }
 
 static int tracing_release(struct inode *inode, struct file *file)
 {
+       struct trace_array *tr = inode->i_private;
        struct seq_file *m = file->private_data;
        struct trace_iterator *iter;
-       struct trace_array *tr;
        int cpu;
 
-       /* Writes do not use seq_file, need to grab tr from inode */
        if (!(file->f_mode & FMODE_READ)) {
-               struct trace_cpu *tc = inode->i_private;
-
-               trace_array_put(tc->tr);
+               trace_array_put(tr);
                return 0;
        }
 
+       /* Writes do not use seq_file */
        iter = m->private;
-       tr = iter->tr;
-
        mutex_lock(&trace_types_lock);
 
        for_each_tracing_cpu(cpu) {
@@ -3044,15 +3032,6 @@ static int tracing_release_generic_tr(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int tracing_release_generic_tc(struct inode *inode, struct file *file)
-{
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
-
-       trace_array_put(tr);
-       return 0;
-}
-
 static int tracing_single_release_tr(struct inode *inode, struct file *file)
 {
        struct trace_array *tr = inode->i_private;
@@ -3064,8 +3043,7 @@ static int tracing_single_release_tr(struct inode *inode, struct file *file)
 
 static int tracing_open(struct inode *inode, struct file *file)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        int ret = 0;
 
@@ -3073,16 +3051,17 @@ static int tracing_open(struct inode *inode, struct file *file)
                return -ENODEV;
 
        /* If this file was open for write, then erase contents */
-       if ((file->f_mode & FMODE_WRITE) &&
-           (file->f_flags & O_TRUNC)) {
-               if (tc->cpu == RING_BUFFER_ALL_CPUS)
+       if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
+               int cpu = tracing_get_cpu(inode);
+
+               if (cpu == RING_BUFFER_ALL_CPUS)
                        tracing_reset_online_cpus(&tr->trace_buffer);
                else
-                       tracing_reset(&tr->trace_buffer, tc->cpu);
+                       tracing_reset(&tr->trace_buffer, cpu);
        }
 
        if (file->f_mode & FMODE_READ) {
-               iter = __tracing_open(tr, tc, inode, file, false);
+               iter = __tracing_open(inode, file, false);
                if (IS_ERR(iter))
                        ret = PTR_ERR(iter);
                else if (trace_flags & TRACE_ITER_LATENCY_FMT)
@@ -3948,8 +3927,7 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_open_pipe(struct inode *inode, struct file *filp)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        int ret = 0;
 
@@ -3995,9 +3973,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
        if (trace_clocks[tr->clock_id].in_ns)
                iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
-       iter->cpu_file = tc->cpu;
-       iter->tr = tc->tr;
-       iter->trace_buffer = &tc->tr->trace_buffer;
+       iter->tr = tr;
+       iter->trace_buffer = &tr->trace_buffer;
+       iter->cpu_file = tracing_get_cpu(inode);
        mutex_init(&iter->mutex);
        filp->private_data = iter;
 
@@ -4020,8 +3998,7 @@ fail:
 static int tracing_release_pipe(struct inode *inode, struct file *file)
 {
        struct trace_iterator *iter = file->private_data;
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
 
        mutex_lock(&trace_types_lock);
 
@@ -4374,15 +4351,16 @@ static ssize_t
 tracing_entries_read(struct file *filp, char __user *ubuf,
                     size_t cnt, loff_t *ppos)
 {
-       struct trace_cpu *tc = filp->private_data;
-       struct trace_array *tr = tc->tr;
+       struct inode *inode = file_inode(filp);
+       struct trace_array *tr = inode->i_private;
+       int cpu = tracing_get_cpu(inode);
        char buf[64];
        int r = 0;
        ssize_t ret;
 
        mutex_lock(&trace_types_lock);
 
-       if (tc->cpu == RING_BUFFER_ALL_CPUS) {
+       if (cpu == RING_BUFFER_ALL_CPUS) {
                int cpu, buf_size_same;
                unsigned long size;
 
@@ -4409,7 +4387,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
                } else
                        r = sprintf(buf, "X\n");
        } else
-               r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10);
+               r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10);
 
        mutex_unlock(&trace_types_lock);
 
@@ -4421,7 +4399,8 @@ static ssize_t
 tracing_entries_write(struct file *filp, const char __user *ubuf,
                      size_t cnt, loff_t *ppos)
 {
-       struct trace_cpu *tc = filp->private_data;
+       struct inode *inode = file_inode(filp);
+       struct trace_array *tr = inode->i_private;
        unsigned long val;
        int ret;
 
@@ -4435,8 +4414,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
 
        /* value is in KB */
        val <<= 10;
-
-       ret = tracing_resize_ring_buffer(tc->tr, val, tc->cpu);
+       ret = tracing_resize_ring_buffer(tr, val, tracing_get_cpu(inode));
        if (ret < 0)
                return ret;
 
@@ -4697,8 +4675,7 @@ struct ftrace_buffer_info {
 #ifdef CONFIG_TRACER_SNAPSHOT
 static int tracing_snapshot_open(struct inode *inode, struct file *file)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct trace_iterator *iter;
        struct seq_file *m;
        int ret = 0;
@@ -4707,7 +4684,7 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
                return -ENODEV;
 
        if (file->f_mode & FMODE_READ) {
-               iter = __tracing_open(tr, tc, inode, file, true);
+               iter = __tracing_open(inode, file, true);
                if (IS_ERR(iter))
                        ret = PTR_ERR(iter);
        } else {
@@ -4724,8 +4701,8 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
                ret = 0;
 
                iter->tr = tr;
-               iter->trace_buffer = &tc->tr->max_buffer;
-               iter->cpu_file = tc->cpu;
+               iter->trace_buffer = &tr->max_buffer;
+               iter->cpu_file = tracing_get_cpu(inode);
                m->private = iter;
                file->private_data = m;
        }
@@ -4884,11 +4861,11 @@ static const struct file_operations tracing_pipe_fops = {
 };
 
 static const struct file_operations tracing_entries_fops = {
-       .open           = tracing_open_generic_tc,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_entries_read,
        .write          = tracing_entries_write,
        .llseek         = generic_file_llseek,
-       .release        = tracing_release_generic_tc,
+       .release        = tracing_release_generic_tr,
 };
 
 static const struct file_operations tracing_total_entries_fops = {
@@ -4940,8 +4917,7 @@ static const struct file_operations snapshot_raw_fops = {
 
 static int tracing_buffers_open(struct inode *inode, struct file *filp)
 {
-       struct trace_cpu *tc = inode->i_private;
-       struct trace_array *tr = tc->tr;
+       struct trace_array *tr = inode->i_private;
        struct ftrace_buffer_info *info;
        int ret;
 
@@ -4960,7 +4936,7 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
        mutex_lock(&trace_types_lock);
 
        info->iter.tr           = tr;
-       info->iter.cpu_file     = tc->cpu;
+       info->iter.cpu_file     = tracing_get_cpu(inode);
        info->iter.trace        = tr->current_trace;
        info->iter.trace_buffer = &tr->trace_buffer;
        info->spare             = NULL;
@@ -5277,14 +5253,14 @@ static ssize_t
 tracing_stats_read(struct file *filp, char __user *ubuf,
                   size_t count, loff_t *ppos)
 {
-       struct trace_cpu *tc = filp->private_data;
-       struct trace_array *tr = tc->tr;
+       struct inode *inode = file_inode(filp);
+       struct trace_array *tr = inode->i_private;
        struct trace_buffer *trace_buf = &tr->trace_buffer;
+       int cpu = tracing_get_cpu(inode);
        struct trace_seq *s;
        unsigned long cnt;
        unsigned long long t;
        unsigned long usec_rem;
-       int cpu = tc->cpu;
 
        s = kmalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
@@ -5337,10 +5313,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 }
 
 static const struct file_operations tracing_stats_fops = {
-       .open           = tracing_open_generic_tc,
+       .open           = tracing_open_generic_tr,
        .read           = tracing_stats_read,
        .llseek         = generic_file_llseek,
-       .release        = tracing_release_generic_tc,
+       .release        = tracing_release_generic_tr,
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -5529,10 +5505,20 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)
        return tr->percpu_dir;
 }
 
+static struct dentry *
+trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
+                     void *data, long cpu, const struct file_operations *fops)
+{
+       struct dentry *ret = trace_create_file(name, mode, parent, data, fops);
+
+       if (ret) /* See tracing_get_cpu() */
+               ret->d_inode->i_cdev = (void *)(cpu + 1);
+       return ret;
+}
+
 static void
 tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 {
-       struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, cpu);
        struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu);
        struct dentry *d_cpu;
        char cpu_dir[30]; /* 30 characters should be more than enough */
@@ -5548,28 +5534,28 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
        }
 
        /* per cpu trace_pipe */
-       trace_create_file("trace_pipe", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_pipe_fops);
+       trace_create_cpu_file("trace_pipe", 0444, d_cpu,
+                               tr, cpu, &tracing_pipe_fops);
 
        /* per cpu trace */
-       trace_create_file("trace", 0644, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_fops);
+       trace_create_cpu_file("trace", 0644, d_cpu,
+                               tr, cpu, &tracing_fops);
 
-       trace_create_file("trace_pipe_raw", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_buffers_fops);
+       trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu,
+                               tr, cpu, &tracing_buffers_fops);
 
-       trace_create_file("stats", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_stats_fops);
+       trace_create_cpu_file("stats", 0444, d_cpu,
+                               tr, cpu, &tracing_stats_fops);
 
-       trace_create_file("buffer_size_kb", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &tracing_entries_fops);
+       trace_create_cpu_file("buffer_size_kb", 0444, d_cpu,
+                               tr, cpu, &tracing_entries_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-       trace_create_file("snapshot", 0644, d_cpu,
-                         (void *)&data->trace_cpu, &snapshot_fops);
+       trace_create_cpu_file("snapshot", 0644, d_cpu,
+                               tr, cpu, &snapshot_fops);
 
-       trace_create_file("snapshot_raw", 0444, d_cpu,
-                       (void *)&data->trace_cpu, &snapshot_raw_fops);
+       trace_create_cpu_file("snapshot_raw", 0444, d_cpu,
+                               tr, cpu, &snapshot_raw_fops);
 #endif
 }
 
@@ -5878,17 +5864,6 @@ struct dentry *trace_instance_dir;
 static void
 init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer);
 
-static void init_trace_buffers(struct trace_array *tr, struct trace_buffer *buf)
-{
-       int cpu;
-
-       for_each_tracing_cpu(cpu) {
-               memset(per_cpu_ptr(buf->data, cpu), 0, sizeof(struct trace_array_cpu));
-               per_cpu_ptr(buf->data, cpu)->trace_cpu.cpu = cpu;
-               per_cpu_ptr(buf->data, cpu)->trace_cpu.tr = tr;
-       }
-}
-
 static int
 allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size)
 {
@@ -5906,8 +5881,6 @@ allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size
                return -ENOMEM;
        }
 
-       init_trace_buffers(tr, buf);
-
        /* Allocate the first page for all buffers */
        set_buffer_entries(&tr->trace_buffer,
                           ring_buffer_size(tr->trace_buffer.buffer, 0));
@@ -5974,10 +5947,6 @@ static int new_instance_create(const char *name)
        if (allocate_trace_buffers(tr, trace_buf_size) < 0)
                goto out_free_tr;
 
-       /* Holder for file callbacks */
-       tr->trace_cpu.cpu = RING_BUFFER_ALL_CPUS;
-       tr->trace_cpu.tr = tr;
-
        tr->dir = debugfs_create_dir(name, trace_instance_dir);
        if (!tr->dir)
                goto out_free_tr;
@@ -6132,13 +6101,13 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
                          tr, &tracing_iter_fops);
 
        trace_create_file("trace", 0644, d_tracer,
-                       (void *)&tr->trace_cpu, &tracing_fops);
+                         tr, &tracing_fops);
 
        trace_create_file("trace_pipe", 0444, d_tracer,
-                       (void *)&tr->trace_cpu, &tracing_pipe_fops);
+                         tr, &tracing_pipe_fops);
 
        trace_create_file("buffer_size_kb", 0644, d_tracer,
-                       (void *)&tr->trace_cpu, &tracing_entries_fops);
+                         tr, &tracing_entries_fops);
 
        trace_create_file("buffer_total_size_kb", 0444, d_tracer,
                          tr, &tracing_total_entries_fops);
@@ -6153,11 +6122,11 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
                          &trace_clock_fops);
 
        trace_create_file("tracing_on", 0644, d_tracer,
-                           tr, &rb_simple_fops);
+                         tr, &rb_simple_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
        trace_create_file("snapshot", 0644, d_tracer,
-                         (void *)&tr->trace_cpu, &snapshot_fops);
+                         tr, &snapshot_fops);
 #endif
 
        for_each_tracing_cpu(cpu)
@@ -6451,10 +6420,6 @@ __init static int tracer_alloc_buffers(void)
 
        global_trace.flags = TRACE_ARRAY_FL_GLOBAL;
 
-       /* Holder for file callbacks */
-       global_trace.trace_cpu.cpu = RING_BUFFER_ALL_CPUS;
-       global_trace.trace_cpu.tr = &global_trace;
-
        INIT_LIST_HEAD(&global_trace.systems);
        INIT_LIST_HEAD(&global_trace.events);
        list_add(&global_trace.list, &ftrace_trace_arrays);
index e7d643b8a907d6dbd027c723115b3d5a21dc9c9e..afaae41b0a0269012ae394dc5df877cd5cf86045 100644 (file)
@@ -130,19 +130,12 @@ enum trace_flag_type {
 
 struct trace_array;
 
-struct trace_cpu {
-       struct trace_array      *tr;
-       struct dentry           *dir;
-       int                     cpu;
-};
-
 /*
  * The CPU trace array - it consists of thousands of trace entries
  * plus some other descriptor data: (for example which task started
  * the trace, etc.)
  */
 struct trace_array_cpu {
-       struct trace_cpu        trace_cpu;
        atomic_t                disabled;
        void                    *buffer_page;   /* ring buffer spare */
 
@@ -196,7 +189,6 @@ struct trace_array {
        bool                    allocated_snapshot;
 #endif
        int                     buffer_disabled;
-       struct trace_cpu        trace_cpu;      /* place holder */
 #ifdef CONFIG_FTRACE_SYSCALLS
        int                     sys_refcount_enter;
        int                     sys_refcount_exit;
index 35da51359d404180c8214c007195e97ca89563dd..71d9f81f6eed17e7623ce9d0b55934acac54358c 100644 (file)
@@ -66,8 +66,6 @@ config CRC16
 
 config CRC_T10DIF
        tristate "CRC calculation for the T10 Data Integrity Field"
-       select CRYPTO
-       select CRYPTO_CRCT10DIF
        help
          This option is only needed if a module that's not in the
          kernel tree needs to calculate CRC checks for use with the
index fe3428c07b47fb605f53dc1f4d9a48f32fce54c1..fbbd66ed86cde5ed7724ed8f17986cdf1a37edaa 100644 (file)
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/crc-t10dif.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <crypto/hash.h>
 
-static struct crypto_shash *crct10dif_tfm;
+/* Table generated using the following polynomium:
+ * x^16 + x^15 + x^11 + x^9 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
+ * gt: 0x8bb7
+ */
+static const __u16 t10_dif_crc_table[256] = {
+       0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B,
+       0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6,
+       0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6,
+       0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B,
+       0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1,
+       0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C,
+       0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C,
+       0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781,
+       0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8,
+       0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255,
+       0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925,
+       0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698,
+       0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472,
+       0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF,
+       0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF,
+       0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02,
+       0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA,
+       0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067,
+       0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17,
+       0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA,
+       0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640,
+       0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD,
+       0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D,
+       0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30,
+       0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759,
+       0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4,
+       0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394,
+       0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29,
+       0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3,
+       0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E,
+       0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E,
+       0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3
+};
 
 __u16 crc_t10dif(const unsigned char *buffer, size_t len)
 {
-       struct {
-               struct shash_desc shash;
-               char ctx[2];
-       } desc;
-       int err;
-
-       desc.shash.tfm = crct10dif_tfm;
-       desc.shash.flags = 0;
-       *(__u16 *)desc.ctx = 0;
+       __u16 crc = 0;
+       unsigned int i;
 
-       err = crypto_shash_update(&desc.shash, buffer, len);
-       BUG_ON(err);
+       for (i = 0 ; i < len ; i++)
+               crc = (crc << 8) ^ t10_dif_crc_table[((crc >> 8) ^ buffer[i]) & 0xff];
 
-       return *(__u16 *)desc.ctx;
+       return crc;
 }
 EXPORT_SYMBOL(crc_t10dif);
 
-static int __init crc_t10dif_mod_init(void)
-{
-       crct10dif_tfm = crypto_alloc_shash("crct10dif", 0, 0);
-       return PTR_RET(crct10dif_tfm);
-}
-
-static void __exit crc_t10dif_mod_fini(void)
-{
-       crypto_free_shash(crct10dif_tfm);
-}
-
-module_init(crc_t10dif_mod_init);
-module_exit(crc_t10dif_mod_fini);
-
 MODULE_DESCRIPTION("T10 DIF CRC calculation");
 MODULE_LICENSE("GPL");
index e2f83591161bbf3e7bf5f70ef732b8cd57b38587..92b9b4324372e8f9d15aba987c3a55a4cb6945c0 100644 (file)
@@ -417,9 +417,11 @@ static void stac_update_outputs(struct hda_codec *codec)
                        val &= ~spec->eapd_mask;
                else
                        val |= spec->eapd_mask;
-               if (spec->gpio_data != val)
+               if (spec->gpio_data != val) {
+                       spec->gpio_data = val;
                        stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir,
                                      val);
+               }
        }
 }
 
@@ -3231,7 +3233,7 @@ static const struct hda_fixup stac927x_fixups[] = {
                        /* configure the analog microphone on some laptops */
                        { 0x0c, 0x90a79130 },
                        /* correct the front output jack as a hp out */
-                       { 0x0f, 0x0227011f },
+                       { 0x0f, 0x0221101f },
                        /* correct the front input jack as a mic */
                        { 0x0e, 0x02a79130 },
                        {}
@@ -3612,20 +3614,18 @@ static int stac_parse_auto_config(struct hda_codec *codec)
 static int stac_init(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
-       unsigned int gpio;
        int i;
 
        /* override some hints */
        stac_store_hints(codec);
 
        /* set up GPIO */
-       gpio = spec->gpio_data;
        /* turn on EAPD statically when spec->eapd_switch isn't set.
         * otherwise, unsol event will turn it on/off dynamically
         */
        if (!spec->eapd_switch)
-               gpio |= spec->eapd_mask;
-       stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio);
+               spec->gpio_data |= spec->eapd_mask;
+       stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
 
        snd_hda_gen_init(codec);
 
@@ -3915,6 +3915,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
 
+       spec->gpio_mask |= spec->eapd_mask;
        if (spec->gpio_led) {
                if (!spec->vref_mute_led_nid) {
                        spec->gpio_mask |= spec->gpio_led;
index ac73c607410a73d92ff84a817c22bf6a99c25d5f..04491f0e8d1bde2636f8772e3b7d3bb65284d44a 100644 (file)
@@ -102,13 +102,13 @@ static struct ep93xx_ac97_info *ep93xx_ac97_info;
 
 static struct ep93xx_dma_data ep93xx_ac97_pcm_out = {
        .name           = "ac97-pcm-out",
-       .dma_port       = EP93XX_DMA_AAC1,
+       .port           = EP93XX_DMA_AAC1,
        .direction      = DMA_MEM_TO_DEV,
 };
 
 static struct ep93xx_dma_data ep93xx_ac97_pcm_in = {
        .name           = "ac97-pcm-in",
-       .dma_port       = EP93XX_DMA_AAC1,
+       .port           = EP93XX_DMA_AAC1,
        .direction      = DMA_DEV_TO_MEM,
 };
 
index 3eeada57e87de68b43394e3440805de03932d890..566a367c94fa0ce71ac04f86686923ed63ece58d 100644 (file)
@@ -1612,7 +1612,7 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 
 static void max98088_sync_cache(struct snd_soc_codec *codec)
 {
-       u16 *reg_cache = codec->reg_cache;
+       u8 *reg_cache = codec->reg_cache;
        int i;
 
        if (!codec->cache_sync)
index d659d3adcfb34e01a04fbc8dfff6fdb9468ba3ad..6c8a9e7bee25c837cd35dc260847e1c778a811b6 100644 (file)
@@ -1527,6 +1527,9 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
        if (IS_ERR(sgtl5000->mclk)) {
                ret = PTR_ERR(sgtl5000->mclk);
                dev_err(&client->dev, "Failed to get mclock: %d\n", ret);
+               /* Defer the probe to see if the clk will be provided later */
+               if (ret == -ENOENT)
+                       return -EPROBE_DEFER;
                return ret;
        }
 
index 0ec070cf7231ebcc39a057061af8995d7f7574ff..d82ee386eab564d352eccd4209dff767b222e6f3 100644 (file)
@@ -3908,10 +3908,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
 {
        /* create platform component name */
        platform->name = fmt_single_name(dev, &platform->id);
-       if (platform->name == NULL) {
-               kfree(platform);
+       if (platform->name == NULL)
                return -ENOMEM;
-       }
 
        platform->dev = dev;
        platform->driver = platform_drv;
index e58233f7df616e6bb406f809cea23069c4059933..6c486625321bebb78b6f66370fda54a49a300fcb 100644 (file)
@@ -389,9 +389,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
        ac97->capture_dma_data.slave_id = of_dma[1];
 
        ac97->playback_dma_data.addr = mem->start + TEGRA20_AC97_FIFO_TX1;
-       ac97->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       ac97->capture_dma_data.maxburst = 4;
-       ac97->capture_dma_data.slave_id = of_dma[0];
+       ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       ac97->playback_dma_data.maxburst = 4;
+       ac97->playback_dma_data.slave_id = of_dma[1];
 
        ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev);
        if (ret)
index 5eaa12cdc6ebd3bfcbd502beb1aff881c111d406..551b3c93ce932c77e9e05de4bcf01f5af63d1c94 100644 (file)
@@ -323,8 +323,8 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
        }
 
        spdif->playback_dma_data.addr = mem->start + TEGRA20_SPDIF_DATA_OUT;
-       spdif->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       spdif->capture_dma_data.maxburst = 4;
+       spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       spdif->playback_dma_data.maxburst = 4;
        spdif->playback_dma_data.slave_id = dmareq->start;
 
        pm_runtime_enable(&pdev->dev);
index 2aa4e13063a8d8d0ab3f5fea2c0849251739ff47..3d2551cc10f2f6fc191acea154ff2a2bc303b09e 100644 (file)
@@ -543,7 +543,7 @@ static snd_pcm_uframes_t usb6fire_pcm_pointer(
        snd_pcm_uframes_t ret;
 
        if (rt->panic || !sub)
-               return SNDRV_PCM_STATE_XRUN;
+               return SNDRV_PCM_POS_XRUN;
 
        spin_lock_irqsave(&sub->lock, flags);
        ret = sub->dma_off;
index 6430ed2a9f65d68d3d7741acd8475b5140c17f51..c21a3df9a0df1ef6900a468ee7af36ad7b57ab19 100644 (file)
@@ -503,7 +503,7 @@ static snd_pcm_uframes_t hiface_pcm_pointer(struct snd_pcm_substream *alsa_sub)
        snd_pcm_uframes_t dma_offset;
 
        if (rt->panic || !sub)
-               return SNDRV_PCM_STATE_XRUN;
+               return SNDRV_PCM_POS_XRUN;
 
        spin_lock_irqsave(&sub->lock, flags);
        dma_offset = sub->dma_off;
index ca9fa4d32e07e3421ce4446f68d9a0601e51ac28..07819bfa7dba30390fedad9e962813f0c95d38c9 100644 (file)
@@ -1026,9 +1026,10 @@ kvp_get_ip_info(int family, char *if_name, int op,
 
                                if (sn_offset == 0)
                                        strcpy(sn_str, cidr_mask);
-                               else
+                               else {
+                                       strcat((char *)ip_buffer->sub_net, ";");
                                        strcat(sn_str, cidr_mask);
-                               strcat((char *)ip_buffer->sub_net, ";");
+                               }
                                sn_offset += strlen(sn_str) + 1;
                        }