Merge tag 'drm-intel-next-fixes-2017-04-27' of git://anongit.freedesktop.org/git...
authorDave Airlie <airlied@redhat.com>
Fri, 28 Apr 2017 19:50:27 +0000 (05:50 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 28 Apr 2017 19:50:27 +0000 (05:50 +1000)
drm/i915 and gvt fixes for drm-next/v4.12

* tag 'drm-intel-next-fixes-2017-04-27' of git://anongit.freedesktop.org/git/drm-intel:
  drm/i915: Confirm the request is still active before adding it to the await
  drm/i915: Avoid busy-spinning on VLV_GLTC_PW_STATUS mmio
  drm/i915/selftests: Allocate inode/file dynamically
  drm/i915: Fix system hang with EI UP masked on Haswell
  drm/i915: checking for NULL instead of IS_ERR() in mock selftests
  drm/i915: Perform link quality check unconditionally during long pulse
  drm/i915: Fix use after free in lpe_audio_platdev_destroy()
  drm/i915: Use the right mapping_gfp_mask for final shmem allocation
  drm/i915: Make legacy cursor updates more unsynced
  drm/i915: Apply a cond_resched() to the saturated signaler
  drm/i915: Park the signaler before sleeping
  drm/i915/gvt: fix a bounds check in ring_id_to_context_switch_event()
  drm/i915/gvt: Fix PTE write flush for taking runtime pm properly
  drm/i915/gvt: remove some debug messages in scheduler timer handler
  drm/i915/gvt: add mmio init for virtual display
  drm/i915/gvt: use directly assignment for structure copying
  drm/i915/gvt: remove redundant ring id check which cause significant CPU misprediction
  drm/i915/gvt: remove redundant platform check for mocs load/restore
  drm/i915/gvt: Align render mmio list to cacheline
  drm/i915/gvt: cleanup some too chatty scheduler message

218 files changed:
.mailmap
MAINTAINERS
Makefile
arch/arm/boot/dts/am335x-baltos.dtsi
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/logicpd-torpedo-som.dtsi
arch/arm/boot/dts/sun8i-a33.dtsi
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smc.S
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-orion5x/Kconfig
arch/arm/plat-orion/common.c
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/ia64/include/asm/asm-prototypes.h [new file with mode: 0644]
arch/ia64/lib/Makefile
arch/parisc/lib/lusercopy.S
arch/x86/entry/vdso/vdso32-setup.c
arch/x86/events/intel/lbr.c
arch/x86/include/asm/elf.h
arch/x86/include/asm/pmem.h
arch/x86/kernel/cpu/intel_rdt_schemata.c
arch/x86/kernel/signal.c
arch/x86/kernel/signal_compat.c
arch/x86/kernel/traps.c
arch/x86/mm/init.c
arch/x86/platform/efi/quirks.c
drivers/acpi/acpica/utresrc.c
drivers/acpi/nfit/core.c
drivers/acpi/scan.c
drivers/ata/pata_atiixp.c
drivers/ata/sata_via.c
drivers/block/zram/zram_drv.c
drivers/char/mem.c
drivers/char/virtio_console.c
drivers/cpufreq/cpufreq.c
drivers/crypto/caam/caampkc.c
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/intern.h
drivers/dax/Kconfig
drivers/dax/dax.c
drivers/dma-buf/dma-buf.c
drivers/firmware/efi/libstub/gop.c
drivers/gpu/drm/arm/malidp_crtc.c
drivers/gpu/drm/arm/malidp_drv.c
drivers/gpu/drm/arm/malidp_drv.h
drivers/gpu/drm/arm/malidp_hw.c
drivers/gpu/drm/arm/malidp_hw.h
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/arm/malidp_regs.h
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/drm_property.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/i915/gvt/cfg_space.c
drivers/gpu/drm/i915/gvt/execlist.c
drivers/gpu/drm/i915/gvt/firmware.c
drivers/gpu/drm/i915/gvt/gvt.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/selftests/mock_dmabuf.c
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sun4i/Makefile
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_crtc.c
drivers/gpu/drm/sun4i/sun4i_crtc.h
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_drv.h
drivers/gpu/drm/sun4i/sun4i_framebuffer.c
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/sun4i/sun4i_layer.h
drivers/gpu/drm/sun4i/sun4i_rgb.c
drivers/gpu/drm/sun4i/sun4i_rgb.h
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tcon.h
drivers/gpu/drm/sun4i/sun4i_tv.c
drivers/gpu/drm/tegra/gem.c
drivers/gpu/drm/udl/udl_dmabuf.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-uclogic.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/input/joystick/xpad.c
drivers/irqchip/irq-imx-gpcv2.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/media/v4l2-core/videobuf2-vmalloc.c
drivers/net/can/ifi_canfd/ifi_canfd.c
drivers/net/can/rcar/rcar_can.c
drivers/net/team/team.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/nvdimm/bus.c
drivers/nvdimm/claim.c
drivers/nvdimm/dimm_devs.c
drivers/nvme/host/fc.c
drivers/nvme/host/rdma.c
drivers/nvme/target/loop.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/samsung/pinctrl-exynos.c
drivers/pinctrl/samsung/pinctrl-exynos.h
drivers/pwm/pwm-lpss-pci.c
drivers/pwm/pwm-lpss-platform.c
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-lpss.h
drivers/pwm/pwm-rockchip.c
drivers/reset/core.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commsup.c
drivers/scsi/ipr.c
drivers/scsi/qedf/qedf_fip.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/staging/android/ion/ion.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/target_core_alua.c
drivers/target/target_core_configfs.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/tty/tty_ldisc.c
drivers/usb/gadget/function/f_tcm.c
drivers/video/fbdev/efifb.c
drivers/video/fbdev/omap/omapfb_main.c
drivers/video/fbdev/ssd1307fb.c
drivers/video/fbdev/xen-fbfront.c
drivers/virtio/virtio.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_pci_common.h
drivers/virtio/virtio_pci_legacy.c
drivers/virtio/virtio_pci_modern.c
fs/btrfs/inode.c
fs/btrfs/super.c
fs/btrfs/volumes.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/hugetlbfs/inode.c
fs/namei.c
fs/orangefs/devorangefs-req.c
fs/orangefs/orangefs-kernel.h
fs/orangefs/super.c
fs/proc/task_mmu.c
include/linux/blkdev.h
include/linux/cgroup.h
include/linux/dma-buf.h
include/linux/mmu_notifier.h
include/linux/reset.h
include/linux/sched.h
include/linux/uio.h
include/linux/virtio.h
include/target/target_core_base.h
include/uapi/linux/Kbuild
include/uapi/linux/virtio_pci.h
kernel/audit.c
kernel/bpf/core.c
kernel/cgroup/cgroup.c
kernel/irq/affinity.c
kernel/kthread.c
kernel/trace/ftrace.c
lib/iov_iter.c
mm/huge_memory.c
mm/z3fold.c
mm/zsmalloc.c
net/bridge/br_device.c
net/bridge/br_if.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/core/datagram.c
net/core/dev.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/l2tp/l2tp_ppp.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_nat_redirect.c
net/netfilter/nft_hash.c
net/netfilter/xt_TCPMSS.c
net/netfilter/xt_TPROXY.c
net/sched/sch_generic.c
net/sctp/socket.c
tools/perf/util/annotate.c
tools/power/cpupower/utils/helpers/cpuid.c
tools/power/x86/turbostat/turbostat.8
tools/power/x86/turbostat/turbostat.c

index e229922dc7f0a30cefab74d0f75313af513965e1..1d6f4e7280dc67f630b79456b3f1e5a4c0a41343 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -99,6 +99,8 @@ Linas Vepstas <linas@austin.ibm.com>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
 Mark Brown <broonie@sirena.org.uk>
+Martin Kepplinger <martink@posteo.de> <martin.kepplinger@theobroma-systems.com>
+Martin Kepplinger <martink@posteo.de> <martin.kepplinger@ginzinger.com>
 Matthieu CASTET <castet.matthieu@free.fr>
 Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@brturbo.com.br>
 Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com>
index 7df09152b2e01eac8c46ccfac2432140b14ac840..66f5b55d205a39b2370a3e2b0202762b2a2f26d8 100644 (file)
@@ -4247,6 +4247,7 @@ L:        dri-devel@lists.freedesktop.org
 S:     Supported
 F:     drivers/gpu/drm/sun4i/
 F:     Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git
 
 DRM DRIVERS FOR AMLOGIC SOCS
 M:     Neil Armstrong <narmstrong@baylibre.com>
@@ -4417,7 +4418,7 @@ DRM DRIVERS FOR STI
 M:     Benjamin Gaignard <benjamin.gaignard@linaro.org>
 M:     Vincent Abriou <vincent.abriou@st.com>
 L:     dri-devel@lists.freedesktop.org
-T:     git http://git.linaro.org/people/benjamin.gaignard/kernel.git
+T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/sti
 F:     Documentation/devicetree/bindings/display/st,stih4xx.txt
@@ -13331,7 +13332,7 @@ F:      drivers/virtio/
 F:     tools/virtio/
 F:     drivers/net/virtio_net.c
 F:     drivers/block/virtio_blk.c
-F:     include/linux/virtio_*.h
+F:     include/linux/virtio*.h
 F:     include/uapi/linux/virtio_*.h
 F:     drivers/crypto/virtio/
 
index efa267a92ba695b00090ad72e9599cfbb9af3b98..5039b9148d15de5762a2a33147535569d5be5746 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 11
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Fearless Coyote
 
 # *DOCUMENTATION*
index efb5eae290a8b7437b95206fa9f69ae4ccecab44..d42b98f15e8b97aaa5956047b51bd1d4a8d610ed 100644 (file)
 
        phy1: ethernet-phy@1 {
                reg = <7>;
+               eee-broken-100tx;
+               eee-broken-1000t;
        };
 };
 
index 9e43c443738a8acedd2c0e160a5b6ddc9e0f6c39..9ba4b18c0cb21711dcd8ef60648a0916914819e7 100644 (file)
        ti,non-removable;
        bus-width = <4>;
        cap-power-off-card;
+       keep-power-in-suspend;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc2_pins>;
 
index 2c9e56f4aac53aa74c206b2cbb3622965d7ab792..bbfb9d5a70a98116d303844a91c6a65dd42cfb39 100644 (file)
                                device_type = "pci";
                                ranges = <0x81000000 0 0          0x03000 0 0x00010000
                                          0x82000000 0 0x20013000 0x13000 0 0xffed000>;
+                               bus-range = <0x00 0xff>;
                                #interrupt-cells = <1>;
                                num-lanes = <1>;
                                linux,pci-domain = <0>;
                                device_type = "pci";
                                ranges = <0x81000000 0 0          0x03000 0 0x00010000
                                          0x82000000 0 0x30013000 0x13000 0 0xffed000>;
+                               bus-range = <0x00 0xff>;
                                #interrupt-cells = <1>;
                                num-lanes = <1>;
                                linux,pci-domain = <1>;
index 8f9a69ca818cecb759e71c1b6b97e4073c3e22e4..efe53998c961244fc0cd1ff32a5e53c885b6322f 100644 (file)
 &i2c3 {
        clock-frequency = <400000>;
        at24@50 {
-               compatible = "at24,24c02";
+               compatible = "atmel,24c64";
                readonly;
                reg = <0x50>;
        };
index 0467fb365bfca714b5ce9021974470002139039f..306af6cadf26033c6102b61c6a6d7693faba30fe 100644 (file)
                        opp-microvolt = <1200000>;
                        clock-latency-ns = <244144>; /* 8 32k periods */
                };
-
-               opp@1200000000 {
-                       opp-hz = /bits/ 64 <1200000000>;
-                       opp-microvolt = <1320000>;
-                       clock-latency-ns = <244144>; /* 8 32k periods */
-               };
        };
 
        cpus {
                        operating-points-v2 = <&cpu0_opp_table>;
                };
 
+               cpu@1 {
+                       operating-points-v2 = <&cpu0_opp_table>;
+               };
+
                cpu@2 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <2>;
+                       operating-points-v2 = <&cpu0_opp_table>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <3>;
+                       operating-points-v2 = <&cpu0_opp_table>;
                };
        };
 
index c4f2ace91ea22d1a6a344388498ec8da30906e63..3089d3bfa19b4a5c595e6872824c81f103d4c5e2 100644 (file)
@@ -270,6 +270,7 @@ extern const struct smp_operations omap4_smp_ops;
 extern int omap4_mpuss_init(void);
 extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
+extern u32 omap4_get_cpu1_ns_pa_addr(void);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
                                        unsigned int power_state)
index d3fb5661bb5d4bc098b05e36f12278301b4c5597..433db6d0b07396288f3b1e38c57d0a64b2ad1e66 100644 (file)
@@ -50,7 +50,7 @@ void omap4_cpu_die(unsigned int cpu)
                omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF);
 
                if (omap_secure_apis_support())
-                       boot_cpu = omap_read_auxcoreboot0();
+                       boot_cpu = omap_read_auxcoreboot0() >> 9;
                else
                        boot_cpu =
                                readl_relaxed(base + OMAP_AUX_CORE_BOOT_0) >> 5;
index 113ab2dd2ee91ccf9c238813bd6c4d7561ff7d97..03ec6d307c8235fc907a599322991b1efd6c27bf 100644 (file)
@@ -64,6 +64,7 @@
 #include "prm-regbits-44xx.h"
 
 static void __iomem *sar_base;
+static u32 old_cpu1_ns_pa_addr;
 
 #if defined(CONFIG_PM) && defined(CONFIG_SMP)
 
@@ -212,6 +213,11 @@ static void __init save_l2x0_context(void)
 {}
 #endif
 
+u32 omap4_get_cpu1_ns_pa_addr(void)
+{
+       return old_cpu1_ns_pa_addr;
+}
+
 /**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
@@ -460,22 +466,30 @@ int __init omap4_mpuss_init(void)
 void __init omap4_mpuss_early_init(void)
 {
        unsigned long startup_pa;
+       void __iomem *ns_pa_addr;
 
-       if (!(cpu_is_omap44xx() || soc_is_omap54xx()))
+       if (!(soc_is_omap44xx() || soc_is_omap54xx()))
                return;
 
        sar_base = omap4_get_sar_ram_base();
 
-       if (cpu_is_omap443x())
+       /* Save old NS_PA_ADDR for validity checks later on */
+       if (soc_is_omap44xx())
+               ns_pa_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+       else
+               ns_pa_addr = sar_base + OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+       old_cpu1_ns_pa_addr = readl_relaxed(ns_pa_addr);
+
+       if (soc_is_omap443x())
                startup_pa = __pa_symbol(omap4_secondary_startup);
-       else if (cpu_is_omap446x())
+       else if (soc_is_omap446x())
                startup_pa = __pa_symbol(omap4460_secondary_startup);
        else if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
                startup_pa = __pa_symbol(omap5_secondary_hyp_startup);
        else
                startup_pa = __pa_symbol(omap5_secondary_startup);
 
-       if (cpu_is_omap44xx())
+       if (soc_is_omap44xx())
                writel_relaxed(startup_pa, sar_base +
                               CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
        else
index fd90125bffc70ad6719bfc2b9f3e22d21b595367..72506e6cf9e7423f946d83e61b5aca66d2fee0c0 100644 (file)
@@ -94,6 +94,5 @@ ENTRY(omap_read_auxcoreboot0)
        ldr     r12, =0x103
        dsb
        smc     #0
-       mov     r0, r0, lsr #9
        ldmfd   sp!, {r2-r12, pc}
 ENDPROC(omap_read_auxcoreboot0)
index 003353b0b7944d9363fb6446e683314823cd82f9..3faf454ba4871c8f60d5e12e912a1ff9dd9af271 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/irqchip/arm-gic.h>
 
+#include <asm/sections.h>
 #include <asm/smp_scu.h>
 #include <asm/virt.h>
 
 
 #define OMAP5_CORE_COUNT       0x2
 
+#define AUX_CORE_BOOT0_GP_RELEASE      0x020
+#define AUX_CORE_BOOT0_HS_RELEASE      0x200
+
 struct omap_smp_config {
        unsigned long cpu1_rstctrl_pa;
        void __iomem *cpu1_rstctrl_va;
        void __iomem *scu_base;
+       void __iomem *wakeupgen_base;
        void *startup_addr;
 };
 
@@ -140,7 +145,6 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
        static struct clockdomain *cpu1_clkdm;
        static bool booted;
        static struct powerdomain *cpu1_pwrdm;
-       void __iomem *base = omap_get_wakeupgen_base();
 
        /*
         * Set synchronisation state between this boot processor
@@ -155,9 +159,11 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
         * A barrier is added to ensure that write buffer is drained
         */
        if (omap_secure_apis_support())
-               omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+               omap_modify_auxcoreboot0(AUX_CORE_BOOT0_HS_RELEASE,
+                                        0xfffffdff);
        else
-               writel_relaxed(0x20, base + OMAP_AUX_CORE_BOOT_0);
+               writel_relaxed(AUX_CORE_BOOT0_GP_RELEASE,
+                              cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
 
        if (!cpu1_clkdm && !cpu1_pwrdm) {
                cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
@@ -261,9 +267,72 @@ static void __init omap4_smp_init_cpus(void)
                set_cpu_possible(i, true);
 }
 
+/*
+ * For now, just make sure the start-up address is not within the booting
+ * kernel space as that means we just overwrote whatever secondary_startup()
+ * code there was.
+ */
+static bool __init omap4_smp_cpu1_startup_valid(unsigned long addr)
+{
+       if ((addr >= __pa(PAGE_OFFSET)) && (addr <= __pa(__bss_start)))
+               return false;
+
+       return true;
+}
+
+/*
+ * We may need to reset CPU1 before configuring, otherwise kexec boot can end
+ * up trying to use old kernel startup address or suspend-resume will
+ * occasionally fail to bring up CPU1 on 4430 if CPU1 fails to enter deeper
+ * idle states.
+ */
+static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
+{
+       unsigned long cpu1_startup_pa, cpu1_ns_pa_addr;
+       bool needs_reset = false;
+       u32 released;
+
+       if (omap_secure_apis_support())
+               released = omap_read_auxcoreboot0() & AUX_CORE_BOOT0_HS_RELEASE;
+       else
+               released = readl_relaxed(cfg.wakeupgen_base +
+                                        OMAP_AUX_CORE_BOOT_0) &
+                                               AUX_CORE_BOOT0_GP_RELEASE;
+       if (released) {
+               pr_warn("smp: CPU1 not parked?\n");
+
+               return;
+       }
+
+       cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base +
+                                       OMAP_AUX_CORE_BOOT_1);
+       cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
+
+       /* Did the configured secondary_startup() get overwritten? */
+       if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa))
+               needs_reset = true;
+
+       /*
+        * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a
+        * deeper idle state in WFI and will wake to an invalid address.
+        */
+       if ((soc_is_omap44xx() || soc_is_omap54xx()) &&
+           !omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
+               needs_reset = true;
+
+       if (!needs_reset || !c->cpu1_rstctrl_va)
+               return;
+
+       pr_info("smp: CPU1 parked within kernel, needs reset (0x%lx 0x%lx)\n",
+               cpu1_startup_pa, cpu1_ns_pa_addr);
+
+       writel_relaxed(1, c->cpu1_rstctrl_va);
+       readl_relaxed(c->cpu1_rstctrl_va);
+       writel_relaxed(0, c->cpu1_rstctrl_va);
+}
+
 static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
 {
-       void __iomem *base = omap_get_wakeupgen_base();
        const struct omap_smp_config *c = NULL;
 
        if (soc_is_omap443x())
@@ -281,6 +350,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
        /* Must preserve cfg.scu_base set earlier */
        cfg.cpu1_rstctrl_pa = c->cpu1_rstctrl_pa;
        cfg.startup_addr = c->startup_addr;
+       cfg.wakeupgen_base = omap_get_wakeupgen_base();
 
        if (soc_is_dra74x() || soc_is_omap54xx()) {
                if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
@@ -299,15 +369,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
        if (cfg.scu_base)
                scu_enable(cfg.scu_base);
 
-       /*
-        * Reset CPU1 before configuring, otherwise kexec will
-        * end up trying to use old kernel startup address.
-        */
-       if (cfg.cpu1_rstctrl_va) {
-               writel_relaxed(1, cfg.cpu1_rstctrl_va);
-               readl_relaxed(cfg.cpu1_rstctrl_va);
-               writel_relaxed(0, cfg.cpu1_rstctrl_va);
-       }
+       omap4_smp_maybe_reset_cpu1(&cfg);
 
        /*
         * Write the address of secondary startup routine into the
@@ -319,7 +381,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
                omap_auxcoreboot_addr(__pa_symbol(cfg.startup_addr));
        else
                writel_relaxed(__pa_symbol(cfg.startup_addr),
-                              base + OMAP_AUX_CORE_BOOT_1);
+                              cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_1);
 }
 
 const struct smp_operations omap4_smp_ops __initconst = {
index e920dd83e443753ccced325ce19c48c6bca398c6..f989145480c8fcd0c947beaadeefe6955896a434 100644 (file)
@@ -222,6 +222,14 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
                                dev_err(dev, "failed to idle\n");
                }
                break;
+       case BUS_NOTIFY_BIND_DRIVER:
+               od = to_omap_device(pdev);
+               if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) &&
+                   pm_runtime_status_suspended(dev)) {
+                       od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
+                       pm_runtime_set_active(dev);
+               }
+               break;
        case BUS_NOTIFY_ADD_DEVICE:
                if (pdev->dev.of_node)
                        omap_device_build_from_dt(pdev);
index 633442ad4e4c16d4c80564410167b53977e7575f..2a7bb6ccdcb7eb219f515c6e0f1ba2bfe573a349 100644 (file)
@@ -6,6 +6,7 @@ menuconfig ARCH_ORION5X
        select GPIOLIB
        select MVEBU_MBUS
        select PCI
+       select PHYLIB if NETDEVICES
        select PLAT_ORION_LEGACY
        help
          Support for the following Marvell Orion 5x series SoCs:
index 9255b6d67ba5e3a3b3586639cadc86342e8b4b04..aff6994950ba6db7eb6579a90cc94e5b2bfc7329 100644 (file)
@@ -468,6 +468,7 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
                    eth_data, &orion_ge11);
 }
 
+#ifdef CONFIG_ARCH_ORION5X
 /*****************************************************************************
  * Ethernet switch
  ****************************************************************************/
@@ -480,6 +481,9 @@ void __init orion_ge00_switch_init(struct dsa_chip_data *d)
        struct mdio_board_info *bd;
        unsigned int i;
 
+       if (!IS_BUILTIN(CONFIG_PHYLIB))
+               return;
+
        for (i = 0; i < ARRAY_SIZE(d->port_names); i++)
                if (!strcmp(d->port_names[i], "cpu"))
                        break;
@@ -493,6 +497,7 @@ void __init orion_ge00_switch_init(struct dsa_chip_data *d)
 
        mdiobus_register_board_info(&orion_ge00_switch_board_info, 1);
 }
+#endif
 
 /*****************************************************************************
  * I2C
index 1c64ea2d23f96a4a990f9f6e8cd4b22fd3fd3dd3..0565779e66fafd9755048c2a1c7f8ebc15533eff 100644 (file)
                usbphy: phy@01c19400 {
                        compatible = "allwinner,sun50i-a64-usb-phy";
                        reg = <0x01c19400 0x14>,
+                             <0x01c1a800 0x4>,
                              <0x01c1b800 0x4>;
                        reg-names = "phy_ctrl",
+                                   "pmu0",
                                    "pmu1";
                        clocks = <&ccu CLK_USB_PHY0>,
                                 <&ccu CLK_USB_PHY1>;
diff --git a/arch/ia64/include/asm/asm-prototypes.h b/arch/ia64/include/asm/asm-prototypes.h
new file mode 100644 (file)
index 0000000..a2c1398
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _ASM_IA64_ASM_PROTOTYPES_H
+#define _ASM_IA64_ASM_PROTOTYPES_H
+
+#include <asm/cacheflush.h>
+#include <asm/checksum.h>
+#include <asm/esi.h>
+#include <asm/ftrace.h>
+#include <asm/page.h>
+#include <asm/pal.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+#include <asm/unwind.h>
+#include <asm/xor.h>
+
+extern const char ia64_ivt[];
+
+signed int __divsi3(signed int, unsigned int);
+signed int __modsi3(signed int, unsigned int);
+
+signed long long __divdi3(signed long long, unsigned long long);
+signed long long __moddi3(signed long long, unsigned long long);
+
+unsigned int __udivsi3(unsigned int, unsigned int);
+unsigned int __umodsi3(unsigned int, unsigned int);
+
+unsigned long long __udivdi3(unsigned long long, unsigned long long);
+unsigned long long __umoddi3(unsigned long long, unsigned long long);
+
+#endif /* _ASM_IA64_ASM_PROTOTYPES_H */
index 1f3d3877618fdc934ab20f07695476206fe35e00..0a40b14407b1692c7a684bb2ea689d130df36805 100644 (file)
@@ -24,25 +24,25 @@ AFLAGS___modsi3.o   =            -DMODULO
 AFLAGS___umodsi3.o     = -DUNSIGNED -DMODULO
 
 $(obj)/__divdi3.o: $(src)/idiv64.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__udivdi3.o: $(src)/idiv64.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__moddi3.o: $(src)/idiv64.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__umoddi3.o: $(src)/idiv64.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__divsi3.o: $(src)/idiv32.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__udivsi3.o: $(src)/idiv32.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__modsi3.o: $(src)/idiv32.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
 
 $(obj)/__umodsi3.o: $(src)/idiv32.S FORCE
-       $(call if_changed_dep,as_o_S)
+       $(call if_changed_rule,as_o_S)
index f01188c044ee83e41ba52162544464781056f262..85c28bb80fb7433dfcfac2fb10f6cc121448119f 100644 (file)
@@ -201,7 +201,7 @@ ENTRY_CFI(pa_memcpy)
        add     dst,len,end
 
        /* short copy with less than 16 bytes? */
-       cmpib,>>=,n 15,len,.Lbyte_loop
+       cmpib,COND(>>=),n 15,len,.Lbyte_loop
 
        /* same alignment? */
        xor     src,dst,t0
@@ -216,7 +216,7 @@ ENTRY_CFI(pa_memcpy)
        /* loop until we are 64-bit aligned */
 .Lalign_loop64:
        extru   dst,31,3,t1
-       cmpib,=,n       0,t1,.Lcopy_loop_16
+       cmpib,=,n       0,t1,.Lcopy_loop_16_start
 20:    ldb,ma  1(srcspc,src),t1
 21:    stb,ma  t1,1(dstspc,dst)
        b       .Lalign_loop64
@@ -225,6 +225,7 @@ ENTRY_CFI(pa_memcpy)
        ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done)
        ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done)
 
+.Lcopy_loop_16_start:
        ldi     31,t0
 .Lcopy_loop_16:
        cmpb,COND(>>=),n t0,len,.Lword_loop
@@ -267,7 +268,7 @@ ENTRY_CFI(pa_memcpy)
        /* loop until we are 32-bit aligned */
 .Lalign_loop32:
        extru   dst,31,2,t1
-       cmpib,=,n       0,t1,.Lcopy_loop_4
+       cmpib,=,n       0,t1,.Lcopy_loop_8
 20:    ldb,ma  1(srcspc,src),t1
 21:    stb,ma  t1,1(dstspc,dst)
        b       .Lalign_loop32
@@ -277,7 +278,7 @@ ENTRY_CFI(pa_memcpy)
        ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done)
 
 
-.Lcopy_loop_4:
+.Lcopy_loop_8:
        cmpib,COND(>>=),n 15,len,.Lbyte_loop
 
 10:    ldw     0(srcspc,src),t1
@@ -299,7 +300,7 @@ ENTRY_CFI(pa_memcpy)
        ASM_EXCEPTIONTABLE_ENTRY(16b,.Lcopy_done)
        ASM_EXCEPTIONTABLE_ENTRY(17b,.Lcopy_done)
 
-       b       .Lcopy_loop_4
+       b       .Lcopy_loop_8
        ldo     -16(len),len
 
 .Lbyte_loop:
@@ -324,7 +325,7 @@ ENTRY_CFI(pa_memcpy)
 .Lunaligned_copy:
        /* align until dst is 32bit-word-aligned */
        extru   dst,31,2,t1
-       cmpib,COND(=),n 0,t1,.Lcopy_dstaligned
+       cmpib,=,n       0,t1,.Lcopy_dstaligned
 20:    ldb     0(srcspc,src),t1
        ldo     1(src),src
 21:    stb,ma  t1,1(dstspc,dst)
@@ -362,7 +363,7 @@ ENTRY_CFI(pa_memcpy)
        cmpiclr,<> 1,t0,%r0
        b,n .Lcase1
 .Lcase0:
-       cmpb,= %r0,len,.Lcda_finish
+       cmpb,COND(=) %r0,len,.Lcda_finish
        nop
 
 1:     ldw,ma 4(srcspc,src), a3
@@ -376,7 +377,7 @@ ENTRY_CFI(pa_memcpy)
 1:     ldw,ma 4(srcspc,src), a3
        ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault)
        ldo -1(len),len
-       cmpb,=,n %r0,len,.Ldo0
+       cmpb,COND(=),n %r0,len,.Ldo0
 .Ldo4:
 1:     ldw,ma 4(srcspc,src), a0
        ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault)
@@ -402,7 +403,7 @@ ENTRY_CFI(pa_memcpy)
 1:     stw,ma t0, 4(dstspc,dst)
        ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done)
        ldo -4(len),len
-       cmpb,<> %r0,len,.Ldo4
+       cmpb,COND(<>) %r0,len,.Ldo4
        nop
 .Ldo0:
        shrpw a2, a3, %sar, t0
@@ -436,14 +437,14 @@ ENTRY_CFI(pa_memcpy)
        /* fault exception fixup handlers: */
 #ifdef CONFIG_64BIT
 .Lcopy16_fault:
-10:    b       .Lcopy_done
-       std,ma  t1,8(dstspc,dst)
+       b       .Lcopy_done
+10:    std,ma  t1,8(dstspc,dst)
        ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done)
 #endif
 
 .Lcopy8_fault:
-10:    b       .Lcopy_done
-       stw,ma  t1,4(dstspc,dst)
+       b       .Lcopy_done
+10:    stw,ma  t1,4(dstspc,dst)
        ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done)
 
        .exit
index 7853b53959cd35a8d555a5ddebfbb4af1f40562a..3f9d1a83891adf9f47cba058078b447fb1de7ecf 100644 (file)
@@ -30,8 +30,10 @@ static int __init vdso32_setup(char *s)
 {
        vdso32_enabled = simple_strtoul(s, NULL, 0);
 
-       if (vdso32_enabled > 1)
+       if (vdso32_enabled > 1) {
                pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled\n");
+               vdso32_enabled = 0;
+       }
 
        return 1;
 }
@@ -62,13 +64,18 @@ subsys_initcall(sysenter_setup);
 /* Register vsyscall32 into the ABI table */
 #include <linux/sysctl.h>
 
+static const int zero;
+static const int one = 1;
+
 static struct ctl_table abi_table2[] = {
        {
                .procname       = "vsyscall32",
                .data           = &vdso32_enabled,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = (int *)&zero,
+               .extra2         = (int *)&one,
        },
        {}
 };
index 81b321ace8e0194d3ce18b29fcb42c20b834a918..f924629836a8ec23eefe0642f48c2f898ea84f2b 100644 (file)
@@ -507,6 +507,9 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
                cpuc->lbr_entries[i].to         = msr_lastbranch.to;
                cpuc->lbr_entries[i].mispred    = 0;
                cpuc->lbr_entries[i].predicted  = 0;
+               cpuc->lbr_entries[i].in_tx      = 0;
+               cpuc->lbr_entries[i].abort      = 0;
+               cpuc->lbr_entries[i].cycles     = 0;
                cpuc->lbr_entries[i].reserved   = 0;
        }
        cpuc->lbr_stack.nr = i;
index 9d49c18b5ea9360feb5e5bb1fe378914154f34d5..3762536619f8cb83c17777e60bbd56830d792cde 100644 (file)
@@ -287,7 +287,7 @@ struct task_struct;
 
 #define        ARCH_DLINFO_IA32                                                \
 do {                                                                   \
-       if (vdso32_enabled) {                                           \
+       if (VDSO_CURRENT_BASE) {                                        \
                NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY);                    \
                NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);        \
        }                                                               \
index 2c1ebeb4d7376db6350b7266048a1d37d800ac86..529bb4a6487a9e42d07d0c4ceb226e41b5808f0f 100644 (file)
@@ -55,7 +55,8 @@ static inline int arch_memcpy_from_pmem(void *dst, const void *src, size_t n)
  * @size:      number of bytes to write back
  *
  * Write back a cache range using the CLWB (cache line write back)
- * instruction.
+ * instruction. Note that @size is internally rounded up to be cache
+ * line size aligned.
  */
 static inline void arch_wb_cache_pmem(void *addr, size_t size)
 {
@@ -69,15 +70,6 @@ static inline void arch_wb_cache_pmem(void *addr, size_t size)
                clwb(p);
 }
 
-/*
- * copy_from_iter_nocache() on x86 only uses non-temporal stores for iovec
- * iterators, so for other types (bvec & kvec) we must do a cache write-back.
- */
-static inline bool __iter_needs_pmem_wb(struct iov_iter *i)
-{
-       return iter_is_iovec(i) == false;
-}
-
 /**
  * arch_copy_from_iter_pmem - copy data from an iterator to PMEM
  * @addr:      PMEM destination address
@@ -94,7 +86,35 @@ static inline size_t arch_copy_from_iter_pmem(void *addr, size_t bytes,
        /* TODO: skip the write-back by always using non-temporal stores */
        len = copy_from_iter_nocache(addr, bytes, i);
 
-       if (__iter_needs_pmem_wb(i))
+       /*
+        * In the iovec case on x86_64 copy_from_iter_nocache() uses
+        * non-temporal stores for the bulk of the transfer, but we need
+        * to manually flush if the transfer is unaligned. A cached
+        * memory copy is used when destination or size is not naturally
+        * aligned. That is:
+        *   - Require 8-byte alignment when size is 8 bytes or larger.
+        *   - Require 4-byte alignment when size is 4 bytes.
+        *
+        * In the non-iovec case the entire destination needs to be
+        * flushed.
+        */
+       if (iter_is_iovec(i)) {
+               unsigned long flushed, dest = (unsigned long) addr;
+
+               if (bytes < 8) {
+                       if (!IS_ALIGNED(dest, 4) || (bytes != 4))
+                               arch_wb_cache_pmem(addr, 1);
+               } else {
+                       if (!IS_ALIGNED(dest, 8)) {
+                               dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
+                               arch_wb_cache_pmem(addr, 1);
+                       }
+
+                       flushed = dest - (unsigned long) addr;
+                       if (bytes > flushed && !IS_ALIGNED(bytes - flushed, 8))
+                               arch_wb_cache_pmem(addr + bytes - 1, 1);
+               }
+       } else
                arch_wb_cache_pmem(addr, bytes);
 
        return len;
index f369cb8db0d5b4332125745dd5a587148f109597..badd2b31a5605f3df24dd250d1f08c9df022b7b2 100644 (file)
@@ -200,11 +200,11 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
        }
 
 out:
-       rdtgroup_kn_unlock(of->kn);
        for_each_enabled_rdt_resource(r) {
                kfree(r->tmp_cbms);
                r->tmp_cbms = NULL;
        }
+       rdtgroup_kn_unlock(of->kn);
        return ret ?: nbytes;
 }
 
index 396c042e9d0ee58873de5c68e6e7e22186070147..cc30a74e4adb2c3499b52488c49498dea1851ae7 100644 (file)
@@ -846,7 +846,7 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
                       task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
                       me->comm, me->pid, where, frame,
                       regs->ip, regs->sp, regs->orig_ax);
-               print_vma_addr(" in ", regs->ip);
+               print_vma_addr(KERN_CONT " in ", regs->ip);
                pr_cont("\n");
        }
 
index ec1f756f9dc9ace1badccd544b6032d64e520360..71beb28600d4531d93a9966401a1ca082a9f0c2e 100644 (file)
@@ -151,8 +151,8 @@ int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from,
 
                                if (from->si_signo == SIGSEGV) {
                                        if (from->si_code == SEGV_BNDERR) {
-                                               compat_uptr_t lower = (unsigned long)&to->si_lower;
-                                               compat_uptr_t upper = (unsigned long)&to->si_upper;
+                                               compat_uptr_t lower = (unsigned long)from->si_lower;
+                                               compat_uptr_t upper = (unsigned long)from->si_upper;
                                                put_user_ex(lower, &to->si_lower);
                                                put_user_ex(upper, &to->si_upper);
                                        }
index 948443e115c147c28a6445eca725fad698d1a56f..4e496379a871687281ddc0c69c0e10d7ec036f09 100644 (file)
@@ -255,7 +255,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
                pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx",
                        tsk->comm, tsk->pid, str,
                        regs->ip, regs->sp, error_code);
-               print_vma_addr(" in ", regs->ip);
+               print_vma_addr(KERN_CONT " in ", regs->ip);
                pr_cont("\n");
        }
 
@@ -519,7 +519,7 @@ do_general_protection(struct pt_regs *regs, long error_code)
                pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx",
                        tsk->comm, task_pid_nr(tsk),
                        regs->ip, regs->sp, error_code);
-               print_vma_addr(" in ", regs->ip);
+               print_vma_addr(KERN_CONT " in ", regs->ip);
                pr_cont("\n");
        }
 
index 22af912d66d258f413414c7355ac82da2814b074..889e7619a0914d87ad49dbb5b960933e5dd316ad 100644 (file)
@@ -643,21 +643,40 @@ void __init init_mem_mapping(void)
  * devmem_is_allowed() checks to see if /dev/mem access to a certain address
  * is valid. The argument is a physical page number.
  *
- *
- * On x86, access has to be given to the first megabyte of ram because that area
- * contains BIOS code and data regions used by X and dosemu and similar apps.
- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
- * mmio resources as well as potential bios/acpi data regions.
+ * On x86, access has to be given to the first megabyte of RAM because that
+ * area traditionally contains BIOS code and data regions used by X, dosemu,
+ * and similar apps. Since they map the entire memory range, the whole range
+ * must be allowed (for mapping), but any areas that would otherwise be
+ * disallowed are flagged as being "zero filled" instead of rejected.
+ * Access has to be given to non-kernel-ram areas as well, these contain the
+ * PCI mmio resources as well as potential bios/acpi data regions.
  */
 int devmem_is_allowed(unsigned long pagenr)
 {
-       if (pagenr < 256)
-               return 1;
-       if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+       if (page_is_ram(pagenr)) {
+               /*
+                * For disallowed memory regions in the low 1MB range,
+                * request that the page be shown as all zeros.
+                */
+               if (pagenr < 256)
+                       return 2;
+
+               return 0;
+       }
+
+       /*
+        * This must follow RAM test, since System RAM is considered a
+        * restricted resource under CONFIG_STRICT_IOMEM.
+        */
+       if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) {
+               /* Low 1MB bypasses iomem restrictions. */
+               if (pagenr < 256)
+                       return 1;
+
                return 0;
-       if (!page_is_ram(pagenr))
-               return 1;
-       return 0;
+       }
+
+       return 1;
 }
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
index 30031d5293c483202c526d5045cda23be6617359..cdfe8c62895981029b8f69218b717b05d0b8961a 100644 (file)
@@ -201,6 +201,10 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
                return;
        }
 
+       /* No need to reserve regions that will never be freed. */
+       if (md.attribute & EFI_MEMORY_RUNTIME)
+               return;
+
        size += addr % EFI_PAGE_SIZE;
        size = round_up(size, EFI_PAGE_SIZE);
        addr = round_down(addr, EFI_PAGE_SIZE);
index c86bae7b1d0fc4d0fce5832a1f2716f59d91a7e6..ff096d9755b925d9f72105f42993ebcc7c0522e1 100644 (file)
@@ -421,10 +421,8 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
 
        ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
 
-       /*
-        * The absolute minimum resource template is one end_tag descriptor.
-        * However, we will treat a lone end_tag as just a simple buffer.
-        */
+       /* The absolute minimum resource template is one end_tag descriptor */
+
        if (aml_length < sizeof(struct aml_resource_end_tag)) {
                return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
        }
@@ -456,8 +454,9 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
                /* Invoke the user function */
 
                if (user_function) {
-                       status = user_function(aml, length, offset,
-                                              resource_index, context);
+                       status =
+                           user_function(aml, length, offset, resource_index,
+                                         context);
                        if (ACPI_FAILURE(status)) {
                                return_ACPI_STATUS(status);
                        }
@@ -481,12 +480,6 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
                                *context = aml;
                        }
 
-                       /* Check if buffer is defined to be longer than the resource length */
-
-                       if (aml_length > (offset + length)) {
-                               return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
-                       }
-
                        /* Normal exit */
 
                        return_ACPI_STATUS(AE_OK);
index 662036bdc65eca8d531886cc658fd9829cc60c00..c8ea9d698cd0f30546d731df6429b3f556140a76 100644 (file)
@@ -1617,7 +1617,11 @@ static int cmp_map(const void *m0, const void *m1)
        const struct nfit_set_info_map *map0 = m0;
        const struct nfit_set_info_map *map1 = m1;
 
-       return map0->region_offset - map1->region_offset;
+       if (map0->region_offset < map1->region_offset)
+               return -1;
+       else if (map0->region_offset > map1->region_offset)
+               return 1;
+       return 0;
 }
 
 /* Retrieve the nth entry referencing this spa */
index 192691880d55c9499e1d77e68058a56d8e5318f3..2433569b02ef5cf40dd82cebec6fc83186f4dc3b 100644 (file)
@@ -1857,15 +1857,20 @@ static void acpi_bus_attach(struct acpi_device *device)
                return;
 
        device->flags.match_driver = true;
-       if (!ret) {
-               ret = device_attach(&device->dev);
-               if (ret < 0)
-                       return;
-
-               if (!ret && device->pnp.type.platform_id)
-                       acpi_default_enumeration(device);
+       if (ret > 0) {
+               acpi_device_set_enumerated(device);
+               goto ok;
        }
 
+       ret = device_attach(&device->dev);
+       if (ret < 0)
+               return;
+
+       if (ret > 0 || !device->pnp.type.platform_id)
+               acpi_device_set_enumerated(device);
+       else
+               acpi_default_enumeration(device);
+
  ok:
        list_for_each_entry(child, &device->children, node)
                acpi_bus_attach(child);
index 6c9aa95a9a050cc070ab222a382f5dabd55ec7ea..49d705c9f0f7b9c6b2ef2549769b6901438c2854 100644 (file)
@@ -278,11 +278,6 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        };
        const struct ata_port_info *ppi[] = { &info, &info };
 
-       /* SB600/700 don't have secondary port wired */
-       if ((pdev->device == PCI_DEVICE_ID_ATI_IXP600_IDE) ||
-               (pdev->device == PCI_DEVICE_ID_ATI_IXP700_IDE))
-               ppi[1] = &ata_dummy_port_info;
-
        return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
                                      ATA_HOST_PARALLEL_SCAN);
 }
index 0636d84fbefe0acc889004b39e83c0137fc0f6a0..f3f538eec7b3bb85b682368ffb42496989c97263 100644 (file)
@@ -644,14 +644,16 @@ static void svia_configure(struct pci_dev *pdev, int board_id,
                pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
        }
 
-       /* enable IRQ on hotplug */
-       pci_read_config_byte(pdev, SVIA_MISC_3, &tmp8);
-       if ((tmp8 & SATA_HOTPLUG) != SATA_HOTPLUG) {
-               dev_dbg(&pdev->dev,
-                       "enabling SATA hotplug (0x%x)\n",
-                       (int) tmp8);
-               tmp8 |= SATA_HOTPLUG;
-               pci_write_config_byte(pdev, SVIA_MISC_3, tmp8);
+       if (board_id == vt6421) {
+               /* enable IRQ on hotplug */
+               pci_read_config_byte(pdev, SVIA_MISC_3, &tmp8);
+               if ((tmp8 & SATA_HOTPLUG) != SATA_HOTPLUG) {
+                       dev_dbg(&pdev->dev,
+                               "enabling SATA hotplug (0x%x)\n",
+                               (int) tmp8);
+                       tmp8 |= SATA_HOTPLUG;
+                       pci_write_config_byte(pdev, SVIA_MISC_3, tmp8);
+               }
        }
 
        /*
index dceb5edd1e5455f4c1b101e8ad3ce4dba46ac22f..0c09d42561081ebb393398ae21a6900283d8f007 100644 (file)
@@ -523,7 +523,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
 
        cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
        if (size == PAGE_SIZE) {
-               copy_page(mem, cmem);
+               memcpy(mem, cmem, PAGE_SIZE);
        } else {
                struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
 
@@ -717,7 +717,7 @@ compress_again:
 
        if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
                src = kmap_atomic(page);
-               copy_page(cmem, src);
+               memcpy(cmem, src, PAGE_SIZE);
                kunmap_atomic(src);
        } else {
                memcpy(cmem, src, clen);
@@ -928,7 +928,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
        }
 
        index = sector >> SECTORS_PER_PAGE_SHIFT;
-       offset = sector & (SECTORS_PER_PAGE - 1) << SECTOR_SHIFT;
+       offset = (sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
 
        bv.bv_page = page;
        bv.bv_len = PAGE_SIZE;
index 6d9cc2d39d22306fd68f30bac6f4a60e6cfa5a87..7e4a9d1296bb7fb666f6b37ced2757a8585b7d75 100644 (file)
@@ -60,6 +60,10 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
 #endif
 
 #ifdef CONFIG_STRICT_DEVMEM
+static inline int page_is_allowed(unsigned long pfn)
+{
+       return devmem_is_allowed(pfn);
+}
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
        u64 from = ((u64)pfn) << PAGE_SHIFT;
@@ -75,6 +79,10 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
        return 1;
 }
 #else
+static inline int page_is_allowed(unsigned long pfn)
+{
+       return 1;
+}
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
        return 1;
@@ -122,23 +130,31 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 
        while (count > 0) {
                unsigned long remaining;
+               int allowed;
 
                sz = size_inside_page(p, count);
 
-               if (!range_is_allowed(p >> PAGE_SHIFT, count))
+               allowed = page_is_allowed(p >> PAGE_SHIFT);
+               if (!allowed)
                        return -EPERM;
+               if (allowed == 2) {
+                       /* Show zeros for restricted memory. */
+                       remaining = clear_user(buf, sz);
+               } else {
+                       /*
+                        * On ia64 if a page has been mapped somewhere as
+                        * uncached, then it must also be accessed uncached
+                        * by the kernel or data corruption may occur.
+                        */
+                       ptr = xlate_dev_mem_ptr(p);
+                       if (!ptr)
+                               return -EFAULT;
 
-               /*
-                * On ia64 if a page has been mapped somewhere as uncached, then
-                * it must also be accessed uncached by the kernel or data
-                * corruption may occur.
-                */
-               ptr = xlate_dev_mem_ptr(p);
-               if (!ptr)
-                       return -EFAULT;
+                       remaining = copy_to_user(buf, ptr, sz);
+
+                       unxlate_dev_mem_ptr(p, ptr);
+               }
 
-               remaining = copy_to_user(buf, ptr, sz);
-               unxlate_dev_mem_ptr(p, ptr);
                if (remaining)
                        return -EFAULT;
 
@@ -181,30 +197,36 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
 #endif
 
        while (count > 0) {
+               int allowed;
+
                sz = size_inside_page(p, count);
 
-               if (!range_is_allowed(p >> PAGE_SHIFT, sz))
+               allowed = page_is_allowed(p >> PAGE_SHIFT);
+               if (!allowed)
                        return -EPERM;
 
-               /*
-                * On ia64 if a page has been mapped somewhere as uncached, then
-                * it must also be accessed uncached by the kernel or data
-                * corruption may occur.
-                */
-               ptr = xlate_dev_mem_ptr(p);
-               if (!ptr) {
-                       if (written)
-                               break;
-                       return -EFAULT;
-               }
+               /* Skip actual writing when a page is marked as restricted. */
+               if (allowed == 1) {
+                       /*
+                        * On ia64 if a page has been mapped somewhere as
+                        * uncached, then it must also be accessed uncached
+                        * by the kernel or data corruption may occur.
+                        */
+                       ptr = xlate_dev_mem_ptr(p);
+                       if (!ptr) {
+                               if (written)
+                                       break;
+                               return -EFAULT;
+                       }
 
-               copied = copy_from_user(ptr, buf, sz);
-               unxlate_dev_mem_ptr(p, ptr);
-               if (copied) {
-                       written += sz - copied;
-                       if (written)
-                               break;
-                       return -EFAULT;
+                       copied = copy_from_user(ptr, buf, sz);
+                       unxlate_dev_mem_ptr(p, ptr);
+                       if (copied) {
+                               written += sz - copied;
+                               if (written)
+                                       break;
+                               return -EFAULT;
+                       }
                }
 
                buf += sz;
index e9b7e0b3cabe60d3be3ab8a092159b137854d8ec..87fe111d0be6b03ec8157f0a688046d490d7e887 100644 (file)
@@ -2202,14 +2202,16 @@ static int virtcons_freeze(struct virtio_device *vdev)
 
        vdev->config->reset(vdev);
 
-       virtqueue_disable_cb(portdev->c_ivq);
+       if (use_multiport(portdev))
+               virtqueue_disable_cb(portdev->c_ivq);
        cancel_work_sync(&portdev->control_work);
        cancel_work_sync(&portdev->config_work);
        /*
         * Once more: if control_work_handler() was running, it would
         * enable the cb as the last step.
         */
-       virtqueue_disable_cb(portdev->c_ivq);
+       if (use_multiport(portdev))
+               virtqueue_disable_cb(portdev->c_ivq);
        remove_controlq_data(portdev);
 
        list_for_each_entry(port, &portdev->ports, list) {
index bc96d423781aa8a300725f8fbe0a052be12cd4b5..0e3f6496524d92c7c1717d8d2259684952d7acb8 100644 (file)
@@ -2398,6 +2398,20 @@ EXPORT_SYMBOL_GPL(cpufreq_boost_enabled);
  *********************************************************************/
 static enum cpuhp_state hp_online;
 
+static int cpuhp_cpufreq_online(unsigned int cpu)
+{
+       cpufreq_online(cpu);
+
+       return 0;
+}
+
+static int cpuhp_cpufreq_offline(unsigned int cpu)
+{
+       cpufreq_offline(cpu);
+
+       return 0;
+}
+
 /**
  * cpufreq_register_driver - register a CPU Frequency driver
  * @driver_data: A struct cpufreq_driver containing the values#
@@ -2460,8 +2474,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
        }
 
        ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "cpufreq:online",
-                                       cpufreq_online,
-                                       cpufreq_offline);
+                                       cpuhp_cpufreq_online,
+                                       cpuhp_cpufreq_offline);
        if (ret < 0)
                goto err_if_unreg;
        hp_online = ret;
index 32100c4851dd4bd94b9b5b6814558812d8b13629..49cbdcba7883072decb2683857ebb8da856cd68c 100644 (file)
@@ -506,7 +506,7 @@ static int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
        ctx->dev = caam_jr_alloc();
 
        if (IS_ERR(ctx->dev)) {
-               dev_err(ctx->dev, "Job Ring Device allocation for transform failed\n");
+               pr_err("Job Ring Device allocation for transform failed\n");
                return PTR_ERR(ctx->dev);
        }
 
index fef39f9f41ee200c5ed7138edae76beaefdff3cb..5d7f73d60515effd80861603cb183595ea7fbb85 100644 (file)
@@ -281,7 +281,8 @@ static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
                        /* Try to run it through DECO0 */
                        ret = run_descriptor_deco0(ctrldev, desc, &status);
 
-                       if (ret || status) {
+                       if (ret ||
+                           (status && status != JRSTA_SSRC_JUMP_HALT_CC)) {
                                dev_err(ctrldev,
                                        "Failed to deinstantiate RNG4 SH%d\n",
                                        sh_idx);
@@ -301,15 +302,13 @@ static int caam_remove(struct platform_device *pdev)
        struct device *ctrldev;
        struct caam_drv_private *ctrlpriv;
        struct caam_ctrl __iomem *ctrl;
-       int ring;
 
        ctrldev = &pdev->dev;
        ctrlpriv = dev_get_drvdata(ctrldev);
        ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
 
-       /* Remove platform devices for JobRs */
-       for (ring = 0; ring < ctrlpriv->total_jobrs; ring++)
-               of_device_unregister(ctrlpriv->jrpdev[ring]);
+       /* Remove platform devices under the crypto node */
+       of_platform_depopulate(ctrldev);
 
        /* De-initialize RNG state handles initialized by this driver. */
        if (ctrlpriv->rng4_sh_init)
@@ -418,10 +417,21 @@ DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u32_ro, caam_debugfs_u32_get, NULL, "%llu\n");
 DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u64_ro, caam_debugfs_u64_get, NULL, "%llu\n");
 #endif
 
+static const struct of_device_id caam_match[] = {
+       {
+               .compatible = "fsl,sec-v4.0",
+       },
+       {
+               .compatible = "fsl,sec4.0",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, caam_match);
+
 /* Probe routine for CAAM top (controller) level */
 static int caam_probe(struct platform_device *pdev)
 {
-       int ret, ring, ridx, rspec, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+       int ret, ring, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
        u64 caam_id;
        struct device *dev;
        struct device_node *nprop, *np;
@@ -597,47 +607,24 @@ static int caam_probe(struct platform_device *pdev)
                goto iounmap_ctrl;
        }
 
-       /*
-        * Detect and enable JobRs
-        * First, find out how many ring spec'ed, allocate references
-        * for all, then go probe each one.
-        */
-       rspec = 0;
-       for_each_available_child_of_node(nprop, np)
-               if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") ||
-                   of_device_is_compatible(np, "fsl,sec4.0-job-ring"))
-                       rspec++;
-
-       ctrlpriv->jrpdev = devm_kcalloc(&pdev->dev, rspec,
-                                       sizeof(*ctrlpriv->jrpdev), GFP_KERNEL);
-       if (ctrlpriv->jrpdev == NULL) {
-               ret = -ENOMEM;
+       ret = of_platform_populate(nprop, caam_match, NULL, dev);
+       if (ret) {
+               dev_err(dev, "JR platform devices creation error\n");
                goto iounmap_ctrl;
        }
 
        ring = 0;
-       ridx = 0;
-       ctrlpriv->total_jobrs = 0;
        for_each_available_child_of_node(nprop, np)
                if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") ||
                    of_device_is_compatible(np, "fsl,sec4.0-job-ring")) {
-                       ctrlpriv->jrpdev[ring] =
-                               of_platform_device_create(np, NULL, dev);
-                       if (!ctrlpriv->jrpdev[ring]) {
-                               pr_warn("JR physical index %d: Platform device creation error\n",
-                                       ridx);
-                               ridx++;
-                               continue;
-                       }
                        ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *)
                                             ((__force uint8_t *)ctrl +
-                                            (ridx + JR_BLOCK_NUMBER) *
+                                            (ring + JR_BLOCK_NUMBER) *
                                              BLOCK_OFFSET
                                             );
                        ctrlpriv->total_jobrs++;
                        ring++;
-                       ridx++;
-       }
+               }
 
        /* Check to see if QI present. If so, enable */
        ctrlpriv->qi_present =
@@ -847,17 +834,6 @@ disable_caam_ipg:
        return ret;
 }
 
-static struct of_device_id caam_match[] = {
-       {
-               .compatible = "fsl,sec-v4.0",
-       },
-       {
-               .compatible = "fsl,sec4.0",
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, caam_match);
-
 static struct platform_driver caam_driver = {
        .driver = {
                .name = "caam",
index e2bcacc1a921675cf30f70a40816e1306a8c3ef9..dbed8baeebe5d4765b741f562b99df206bc4b47b 100644 (file)
@@ -66,7 +66,6 @@ struct caam_drv_private_jr {
 struct caam_drv_private {
 
        struct device *dev;
-       struct platform_device **jrpdev; /* Alloc'ed array per sub-device */
        struct platform_device *pdev;
 
        /* Physical-presence section */
index 3e2ab3b14eea205f19e8b436291e5117cec9567d..9e95bf94eb13ff2e830905694e0ce4c045fc76b1 100644 (file)
@@ -2,6 +2,7 @@ menuconfig DEV_DAX
        tristate "DAX: direct access to differentiated memory"
        default m if NVDIMM_DAX
        depends on TRANSPARENT_HUGEPAGE
+       select SRCU
        help
          Support raw access to differentiated (persistence, bandwidth,
          latency...) memory via an mmap(2) capable character
index 80c6db279ae10cb8558b2e90a91a4c4dafa917e0..806f180c80d816b313319f960479a7ad2848c672 100644 (file)
@@ -25,6 +25,7 @@
 #include "dax.h"
 
 static dev_t dax_devt;
+DEFINE_STATIC_SRCU(dax_srcu);
 static struct class *dax_class;
 static DEFINE_IDA(dax_minor_ida);
 static int nr_dax = CONFIG_NR_DEV_DAX;
@@ -60,7 +61,7 @@ struct dax_region {
  * @region - parent region
  * @dev - device backing the character device
  * @cdev - core chardev data
- * @alive - !alive + rcu grace period == no new mappings can be established
+ * @alive - !alive + srcu grace period == no new mappings can be established
  * @id - child id in the region
  * @num_resources - number of physical address extents in this device
  * @res - array of physical address ranges
@@ -569,7 +570,7 @@ static int __dax_dev_pud_fault(struct dax_dev *dax_dev, struct vm_fault *vmf)
 static int dax_dev_huge_fault(struct vm_fault *vmf,
                enum page_entry_size pe_size)
 {
-       int rc;
+       int rc, id;
        struct file *filp = vmf->vma->vm_file;
        struct dax_dev *dax_dev = filp->private_data;
 
@@ -578,7 +579,7 @@ static int dax_dev_huge_fault(struct vm_fault *vmf,
                        ? "write" : "read",
                        vmf->vma->vm_start, vmf->vma->vm_end);
 
-       rcu_read_lock();
+       id = srcu_read_lock(&dax_srcu);
        switch (pe_size) {
        case PE_SIZE_PTE:
                rc = __dax_dev_pte_fault(dax_dev, vmf);
@@ -592,7 +593,7 @@ static int dax_dev_huge_fault(struct vm_fault *vmf,
        default:
                return VM_FAULT_FALLBACK;
        }
-       rcu_read_unlock();
+       srcu_read_unlock(&dax_srcu, id);
 
        return rc;
 }
@@ -713,11 +714,11 @@ static void unregister_dax_dev(void *dev)
         * Note, rcu is not protecting the liveness of dax_dev, rcu is
         * ensuring that any fault handlers that might have seen
         * dax_dev->alive == true, have completed.  Any fault handlers
-        * that start after synchronize_rcu() has started will abort
+        * that start after synchronize_srcu() has started will abort
         * upon seeing dax_dev->alive == false.
         */
        dax_dev->alive = false;
-       synchronize_rcu();
+       synchronize_srcu(&dax_srcu);
        unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1);
        cdev_del(cdev);
        device_unregister(dev);
index f72aaacbe023d702c0256c9dcc5345a63f9fa022..512bdbc23bbb43b85e9da8badbe24bcd64a66872 100644 (file)
@@ -405,8 +405,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
                          || !exp_info->ops->map_dma_buf
                          || !exp_info->ops->unmap_dma_buf
                          || !exp_info->ops->release
-                         || !exp_info->ops->kmap_atomic
-                         || !exp_info->ops->kmap
+                         || !exp_info->ops->map_atomic
+                         || !exp_info->ops->map
                          || !exp_info->ops->mmap)) {
                return ERR_PTR(-EINVAL);
        }
@@ -872,7 +872,7 @@ void *dma_buf_kmap_atomic(struct dma_buf *dmabuf, unsigned long page_num)
 {
        WARN_ON(!dmabuf);
 
-       return dmabuf->ops->kmap_atomic(dmabuf, page_num);
+       return dmabuf->ops->map_atomic(dmabuf, page_num);
 }
 EXPORT_SYMBOL_GPL(dma_buf_kmap_atomic);
 
@@ -889,8 +889,8 @@ void dma_buf_kunmap_atomic(struct dma_buf *dmabuf, unsigned long page_num,
 {
        WARN_ON(!dmabuf);
 
-       if (dmabuf->ops->kunmap_atomic)
-               dmabuf->ops->kunmap_atomic(dmabuf, page_num, vaddr);
+       if (dmabuf->ops->unmap_atomic)
+               dmabuf->ops->unmap_atomic(dmabuf, page_num, vaddr);
 }
 EXPORT_SYMBOL_GPL(dma_buf_kunmap_atomic);
 
@@ -907,7 +907,7 @@ void *dma_buf_kmap(struct dma_buf *dmabuf, unsigned long page_num)
 {
        WARN_ON(!dmabuf);
 
-       return dmabuf->ops->kmap(dmabuf, page_num);
+       return dmabuf->ops->map(dmabuf, page_num);
 }
 EXPORT_SYMBOL_GPL(dma_buf_kmap);
 
@@ -924,8 +924,8 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long page_num,
 {
        WARN_ON(!dmabuf);
 
-       if (dmabuf->ops->kunmap)
-               dmabuf->ops->kunmap(dmabuf, page_num, vaddr);
+       if (dmabuf->ops->unmap)
+               dmabuf->ops->unmap(dmabuf, page_num, vaddr);
 }
 EXPORT_SYMBOL_GPL(dma_buf_kunmap);
 
index 932742e4cf23147e304d6df2a1c8f37c8f89d296..24c461dea7afb146a509e097b581aa2fdaede132 100644 (file)
@@ -149,7 +149,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
                status = __gop_query32(sys_table_arg, gop32, &info, &size,
                                       &current_fb_base);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+               if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+                   info->pixel_format != PIXEL_BLT_ONLY) {
                        /*
                         * Systems that use the UEFI Console Splitter may
                         * provide multiple GOP devices, not all of which are
@@ -266,7 +267,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
                status = __gop_query64(sys_table_arg, gop64, &info, &size,
                                       &current_fb_base);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+               if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+                   info->pixel_format != PIXEL_BLT_ONLY) {
                        /*
                         * Systems that use the UEFI Console Splitter may
                         * provide multiple GOP devices, not all of which are
index f9d665550d3e7a51af064ab9797d207f778f820c..9446a673d46950883e8a21911eaebc90023add20 100644 (file)
@@ -16,6 +16,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <linux/clk.h>
+#include <linux/pm_runtime.h>
 #include <video/videomode.h>
 
 #include "malidp_drv.h"
@@ -35,13 +36,6 @@ static bool malidp_crtc_mode_fixup(struct drm_crtc *crtc,
        long rate, req_rate = mode->crtc_clock * 1000;
 
        if (req_rate) {
-               rate = clk_round_rate(hwdev->mclk, req_rate);
-               if (rate < req_rate) {
-                       DRM_DEBUG_DRIVER("mclk clock unable to reach %d kHz\n",
-                                        mode->crtc_clock);
-                       return false;
-               }
-
                rate = clk_round_rate(hwdev->pxlclk, req_rate);
                if (rate != req_rate) {
                        DRM_DEBUG_DRIVER("pxlclk doesn't support %ld Hz\n",
@@ -58,9 +52,14 @@ static void malidp_crtc_enable(struct drm_crtc *crtc)
        struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
        struct malidp_hw_device *hwdev = malidp->dev;
        struct videomode vm;
+       int err = pm_runtime_get_sync(crtc->dev->dev);
 
-       drm_display_mode_to_videomode(&crtc->state->adjusted_mode, &vm);
+       if (err < 0) {
+               DRM_DEBUG_DRIVER("Failed to enable runtime power management: %d\n", err);
+               return;
+       }
 
+       drm_display_mode_to_videomode(&crtc->state->adjusted_mode, &vm);
        clk_prepare_enable(hwdev->pxlclk);
 
        /* We rely on firmware to set mclk to a sensible level. */
@@ -75,10 +74,254 @@ static void malidp_crtc_disable(struct drm_crtc *crtc)
 {
        struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
        struct malidp_hw_device *hwdev = malidp->dev;
+       int err;
 
        drm_crtc_vblank_off(crtc);
        hwdev->enter_config_mode(hwdev);
        clk_disable_unprepare(hwdev->pxlclk);
+
+       err = pm_runtime_put(crtc->dev->dev);
+       if (err < 0) {
+               DRM_DEBUG_DRIVER("Failed to disable runtime power management: %d\n", err);
+       }
+}
+
+static const struct gamma_curve_segment {
+       u16 start;
+       u16 end;
+} segments[MALIDP_COEFFTAB_NUM_COEFFS] = {
+       /* sector 0 */
+       {    0,    0 }, {    1,    1 }, {    2,    2 }, {    3,    3 },
+       {    4,    4 }, {    5,    5 }, {    6,    6 }, {    7,    7 },
+       {    8,    8 }, {    9,    9 }, {   10,   10 }, {   11,   11 },
+       {   12,   12 }, {   13,   13 }, {   14,   14 }, {   15,   15 },
+       /* sector 1 */
+       {   16,   19 }, {   20,   23 }, {   24,   27 }, {   28,   31 },
+       /* sector 2 */
+       {   32,   39 }, {   40,   47 }, {   48,   55 }, {   56,   63 },
+       /* sector 3 */
+       {   64,   79 }, {   80,   95 }, {   96,  111 }, {  112,  127 },
+       /* sector 4 */
+       {  128,  159 }, {  160,  191 }, {  192,  223 }, {  224,  255 },
+       /* sector 5 */
+       {  256,  319 }, {  320,  383 }, {  384,  447 }, {  448,  511 },
+       /* sector 6 */
+       {  512,  639 }, {  640,  767 }, {  768,  895 }, {  896, 1023 },
+       { 1024, 1151 }, { 1152, 1279 }, { 1280, 1407 }, { 1408, 1535 },
+       { 1536, 1663 }, { 1664, 1791 }, { 1792, 1919 }, { 1920, 2047 },
+       { 2048, 2175 }, { 2176, 2303 }, { 2304, 2431 }, { 2432, 2559 },
+       { 2560, 2687 }, { 2688, 2815 }, { 2816, 2943 }, { 2944, 3071 },
+       { 3072, 3199 }, { 3200, 3327 }, { 3328, 3455 }, { 3456, 3583 },
+       { 3584, 3711 }, { 3712, 3839 }, { 3840, 3967 }, { 3968, 4095 },
+};
+
+#define DE_COEFTAB_DATA(a, b) ((((a) & 0xfff) << 16) | (((b) & 0xfff)))
+
+static void malidp_generate_gamma_table(struct drm_property_blob *lut_blob,
+                                       u32 coeffs[MALIDP_COEFFTAB_NUM_COEFFS])
+{
+       struct drm_color_lut *lut = (struct drm_color_lut *)lut_blob->data;
+       int i;
+
+       for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i) {
+               u32 a, b, delta_in, out_start, out_end;
+
+               delta_in = segments[i].end - segments[i].start;
+               /* DP has 12-bit internal precision for its LUTs. */
+               out_start = drm_color_lut_extract(lut[segments[i].start].green,
+                                                 12);
+               out_end = drm_color_lut_extract(lut[segments[i].end].green, 12);
+               a = (delta_in == 0) ? 0 : ((out_end - out_start) * 256) / delta_in;
+               b = out_start;
+               coeffs[i] = DE_COEFTAB_DATA(a, b);
+       }
+}
+
+/*
+ * Check if there is a new gamma LUT and if it is of an acceptable size. Also,
+ * reject any LUTs that use distinct red, green, and blue curves.
+ */
+static int malidp_crtc_atomic_check_gamma(struct drm_crtc *crtc,
+                                         struct drm_crtc_state *state)
+{
+       struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+       struct drm_color_lut *lut;
+       size_t lut_size;
+       int i;
+
+       if (!state->color_mgmt_changed || !state->gamma_lut)
+               return 0;
+
+       if (crtc->state->gamma_lut &&
+           (crtc->state->gamma_lut->base.id == state->gamma_lut->base.id))
+               return 0;
+
+       if (state->gamma_lut->length % sizeof(struct drm_color_lut))
+               return -EINVAL;
+
+       lut_size = state->gamma_lut->length / sizeof(struct drm_color_lut);
+       if (lut_size != MALIDP_GAMMA_LUT_SIZE)
+               return -EINVAL;
+
+       lut = (struct drm_color_lut *)state->gamma_lut->data;
+       for (i = 0; i < lut_size; ++i)
+               if (!((lut[i].red == lut[i].green) &&
+                     (lut[i].red == lut[i].blue)))
+                       return -EINVAL;
+
+       if (!state->mode_changed) {
+               int ret;
+
+               state->mode_changed = true;
+               /*
+                * Kerneldoc for drm_atomic_helper_check_modeset mandates that
+                * it be invoked when the driver sets ->mode_changed. Since
+                * changing the gamma LUT doesn't depend on any external
+                * resources, it is safe to call it only once.
+                */
+               ret = drm_atomic_helper_check_modeset(crtc->dev, state->state);
+               if (ret)
+                       return ret;
+       }
+
+       malidp_generate_gamma_table(state->gamma_lut, mc->gamma_coeffs);
+       return 0;
+}
+
+/*
+ * Check if there is a new CTM and if it contains valid input. Valid here means
+ * that the number is inside the representable range for a Q3.12 number,
+ * excluding truncating the fractional part of the input data.
+ *
+ * The COLORADJ registers can be changed atomically.
+ */
+static int malidp_crtc_atomic_check_ctm(struct drm_crtc *crtc,
+                                       struct drm_crtc_state *state)
+{
+       struct malidp_crtc_state *mc = to_malidp_crtc_state(state);
+       struct drm_color_ctm *ctm;
+       int i;
+
+       if (!state->color_mgmt_changed)
+               return 0;
+
+       if (!state->ctm)
+               return 0;
+
+       if (crtc->state->ctm && (crtc->state->ctm->base.id ==
+                                state->ctm->base.id))
+               return 0;
+
+       /*
+        * The size of the ctm is checked in
+        * drm_atomic_replace_property_blob_from_id.
+        */
+       ctm = (struct drm_color_ctm *)state->ctm->data;
+       for (i = 0; i < ARRAY_SIZE(ctm->matrix); ++i) {
+               /* Convert from S31.32 to Q3.12. */
+               s64 val = ctm->matrix[i];
+               u32 mag = ((((u64)val) & ~BIT_ULL(63)) >> 20) &
+                         GENMASK_ULL(14, 0);
+
+               /*
+                * Convert to 2s complement and check the destination's top bit
+                * for overflow. NB: Can't check before converting or it'd
+                * incorrectly reject the case:
+                * sign == 1
+                * mag == 0x2000
+                */
+               if (val & BIT_ULL(63))
+                       mag = ~mag + 1;
+               if (!!(val & BIT_ULL(63)) != !!(mag & BIT(14)))
+                       return -EINVAL;
+               mc->coloradj_coeffs[i] = mag;
+       }
+
+       return 0;
+}
+
+static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc,
+                                           struct drm_crtc_state *state)
+{
+       struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+       struct malidp_hw_device *hwdev = malidp->dev;
+       struct malidp_crtc_state *cs = to_malidp_crtc_state(state);
+       struct malidp_se_config *s = &cs->scaler_config;
+       struct drm_plane *plane;
+       struct videomode vm;
+       const struct drm_plane_state *pstate;
+       u32 h_upscale_factor = 0; /* U16.16 */
+       u32 v_upscale_factor = 0; /* U16.16 */
+       u8 scaling = cs->scaled_planes_mask;
+       int ret;
+
+       if (!scaling) {
+               s->scale_enable = false;
+               goto mclk_calc;
+       }
+
+       /* The scaling engine can only handle one plane at a time. */
+       if (scaling & (scaling - 1))
+               return -EINVAL;
+
+       drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
+               struct malidp_plane *mp = to_malidp_plane(plane);
+               u32 phase;
+
+               if (!(mp->layer->id & scaling))
+                       continue;
+
+               /*
+                * Convert crtc_[w|h] to U32.32, then divide by U16.16 src_[w|h]
+                * to get the U16.16 result.
+                */
+               h_upscale_factor = div_u64((u64)pstate->crtc_w << 32,
+                                          pstate->src_w);
+               v_upscale_factor = div_u64((u64)pstate->crtc_h << 32,
+                                          pstate->src_h);
+
+               s->enhancer_enable = ((h_upscale_factor >> 16) >= 2 ||
+                                     (v_upscale_factor >> 16) >= 2);
+
+               s->input_w = pstate->src_w >> 16;
+               s->input_h = pstate->src_h >> 16;
+               s->output_w = pstate->crtc_w;
+               s->output_h = pstate->crtc_h;
+
+#define SE_N_PHASE 4
+#define SE_SHIFT_N_PHASE 12
+               /* Calculate initial_phase and delta_phase for horizontal. */
+               phase = s->input_w;
+               s->h_init_phase =
+                               ((phase << SE_N_PHASE) / s->output_w + 1) / 2;
+
+               phase = s->input_w;
+               phase <<= (SE_SHIFT_N_PHASE + SE_N_PHASE);
+               s->h_delta_phase = phase / s->output_w;
+
+               /* Same for vertical. */
+               phase = s->input_h;
+               s->v_init_phase =
+                               ((phase << SE_N_PHASE) / s->output_h + 1) / 2;
+
+               phase = s->input_h;
+               phase <<= (SE_SHIFT_N_PHASE + SE_N_PHASE);
+               s->v_delta_phase = phase / s->output_h;
+#undef SE_N_PHASE
+#undef SE_SHIFT_N_PHASE
+               s->plane_src_id = mp->layer->id;
+       }
+
+       s->scale_enable = true;
+       s->hcoeff = malidp_se_select_coeffs(h_upscale_factor);
+       s->vcoeff = malidp_se_select_coeffs(v_upscale_factor);
+
+mclk_calc:
+       drm_display_mode_to_videomode(&state->adjusted_mode, &vm);
+       ret = hwdev->se_calc_mclk(hwdev, s, &vm);
+       if (ret < 0)
+               return -EINVAL;
+       return 0;
 }
 
 static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
@@ -90,6 +333,7 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
        const struct drm_plane_state *pstate;
        u32 rot_mem_free, rot_mem_usable;
        int rotated_planes = 0;
+       int ret;
 
        /*
         * check if there is enough rotation memory available for planes
@@ -156,7 +400,11 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
                }
        }
 
-       return 0;
+       ret = malidp_crtc_atomic_check_gamma(crtc, state);
+       ret = ret ? ret : malidp_crtc_atomic_check_ctm(crtc, state);
+       ret = ret ? ret : malidp_crtc_atomic_check_scaling(crtc, state);
+
+       return ret;
 }
 
 static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
@@ -166,6 +414,60 @@ static const struct drm_crtc_helper_funcs malidp_crtc_helper_funcs = {
        .atomic_check = malidp_crtc_atomic_check,
 };
 
+static struct drm_crtc_state *malidp_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+       struct malidp_crtc_state *state, *old_state;
+
+       if (WARN_ON(!crtc->state))
+               return NULL;
+
+       old_state = to_malidp_crtc_state(crtc->state);
+       state = kmalloc(sizeof(*state), GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+       memcpy(state->gamma_coeffs, old_state->gamma_coeffs,
+              sizeof(state->gamma_coeffs));
+       memcpy(state->coloradj_coeffs, old_state->coloradj_coeffs,
+              sizeof(state->coloradj_coeffs));
+       memcpy(&state->scaler_config, &old_state->scaler_config,
+              sizeof(state->scaler_config));
+       state->scaled_planes_mask = 0;
+
+       return &state->base;
+}
+
+static void malidp_crtc_reset(struct drm_crtc *crtc)
+{
+       struct malidp_crtc_state *state = NULL;
+
+       if (crtc->state) {
+               state = to_malidp_crtc_state(crtc->state);
+               __drm_atomic_helper_crtc_destroy_state(crtc->state);
+       }
+
+       kfree(state);
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (state) {
+               crtc->state = &state->base;
+               crtc->state->crtc = crtc;
+       }
+}
+
+static void malidp_crtc_destroy_state(struct drm_crtc *crtc,
+                                     struct drm_crtc_state *state)
+{
+       struct malidp_crtc_state *mali_state = NULL;
+
+       if (state) {
+               mali_state = to_malidp_crtc_state(state);
+               __drm_atomic_helper_crtc_destroy_state(state);
+       }
+
+       kfree(mali_state);
+}
+
 static int malidp_crtc_enable_vblank(struct drm_crtc *crtc)
 {
        struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
@@ -186,12 +488,13 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc)
 }
 
 static const struct drm_crtc_funcs malidp_crtc_funcs = {
+       .gamma_set = drm_atomic_helper_legacy_gamma_set,
        .destroy = drm_crtc_cleanup,
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
-       .reset = drm_atomic_helper_crtc_reset,
-       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+       .reset = malidp_crtc_reset,
+       .atomic_duplicate_state = malidp_crtc_duplicate_state,
+       .atomic_destroy_state = malidp_crtc_destroy_state,
        .enable_vblank = malidp_crtc_enable_vblank,
        .disable_vblank = malidp_crtc_disable_vblank,
 };
@@ -223,11 +526,17 @@ int malidp_crtc_init(struct drm_device *drm)
 
        ret = drm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL,
                                        &malidp_crtc_funcs, NULL);
+       if (ret)
+               goto crtc_cleanup_planes;
 
-       if (!ret) {
-               drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
-               return 0;
-       }
+       drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs);
+       drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE);
+       /* No inverse-gamma: it is per-plane. */
+       drm_crtc_enable_color_mgmt(&malidp->crtc, 0, true, MALIDP_GAMMA_LUT_SIZE);
+
+       malidp_se_set_enh_coeffs(malidp->dev);
+
+       return 0;
 
 crtc_cleanup_planes:
        malidp_de_planes_destroy(drm);
index 898c2b58e73dfd7c89602db4658d2999fe1c4d8f..0d3eb537d08b6adfff835c04399acb587ef12cee 100644 (file)
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/console.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/of_reserved_mem.h>
+#include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 
 #define MALIDP_CONF_VALID_TIMEOUT      250
 
+static void malidp_write_gamma_table(struct malidp_hw_device *hwdev,
+                                    u32 data[MALIDP_COEFFTAB_NUM_COEFFS])
+{
+       int i;
+       /* Update all channels with a single gamma curve. */
+       const u32 gamma_write_mask = GENMASK(18, 16);
+       /*
+        * Always write an entire table, so the address field in
+        * DE_COEFFTAB_ADDR is 0 and we can use the gamma_write_mask bitmask
+        * directly.
+        */
+       malidp_hw_write(hwdev, gamma_write_mask,
+                       hwdev->map.coeffs_base + MALIDP_COEF_TABLE_ADDR);
+       for (i = 0; i < MALIDP_COEFFTAB_NUM_COEFFS; ++i)
+               malidp_hw_write(hwdev, data[i],
+                               hwdev->map.coeffs_base +
+                               MALIDP_COEF_TABLE_DATA);
+}
+
+static void malidp_atomic_commit_update_gamma(struct drm_crtc *crtc,
+                                             struct drm_crtc_state *old_state)
+{
+       struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+       struct malidp_hw_device *hwdev = malidp->dev;
+
+       if (!crtc->state->color_mgmt_changed)
+               return;
+
+       if (!crtc->state->gamma_lut) {
+               malidp_hw_clearbits(hwdev,
+                                   MALIDP_DISP_FUNC_GAMMA,
+                                   MALIDP_DE_DISPLAY_FUNC);
+       } else {
+               struct malidp_crtc_state *mc =
+                       to_malidp_crtc_state(crtc->state);
+
+               if (!old_state->gamma_lut || (crtc->state->gamma_lut->base.id !=
+                                             old_state->gamma_lut->base.id))
+                       malidp_write_gamma_table(hwdev, mc->gamma_coeffs);
+
+               malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_GAMMA,
+                                 MALIDP_DE_DISPLAY_FUNC);
+       }
+}
+
+static
+void malidp_atomic_commit_update_coloradj(struct drm_crtc *crtc,
+                                         struct drm_crtc_state *old_state)
+{
+       struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+       struct malidp_hw_device *hwdev = malidp->dev;
+       int i;
+
+       if (!crtc->state->color_mgmt_changed)
+               return;
+
+       if (!crtc->state->ctm) {
+               malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_CADJ,
+                                   MALIDP_DE_DISPLAY_FUNC);
+       } else {
+               struct malidp_crtc_state *mc =
+                       to_malidp_crtc_state(crtc->state);
+
+               if (!old_state->ctm || (crtc->state->ctm->base.id !=
+                                       old_state->ctm->base.id))
+                       for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; ++i)
+                               malidp_hw_write(hwdev,
+                                               mc->coloradj_coeffs[i],
+                                               hwdev->map.coeffs_base +
+                                               MALIDP_COLOR_ADJ_COEF + 4 * i);
+
+               malidp_hw_setbits(hwdev, MALIDP_DISP_FUNC_CADJ,
+                                 MALIDP_DE_DISPLAY_FUNC);
+       }
+}
+
+static void malidp_atomic_commit_se_config(struct drm_crtc *crtc,
+                                          struct drm_crtc_state *old_state)
+{
+       struct malidp_crtc_state *cs = to_malidp_crtc_state(crtc->state);
+       struct malidp_crtc_state *old_cs = to_malidp_crtc_state(old_state);
+       struct malidp_drm *malidp = crtc_to_malidp_device(crtc);
+       struct malidp_hw_device *hwdev = malidp->dev;
+       struct malidp_se_config *s = &cs->scaler_config;
+       struct malidp_se_config *old_s = &old_cs->scaler_config;
+       u32 se_control = hwdev->map.se_base +
+                        ((hwdev->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
+                        0x10 : 0xC);
+       u32 layer_control = se_control + MALIDP_SE_LAYER_CONTROL;
+       u32 scr = se_control + MALIDP_SE_SCALING_CONTROL;
+       u32 val;
+
+       /* Set SE_CONTROL */
+       if (!s->scale_enable) {
+               val = malidp_hw_read(hwdev, se_control);
+               val &= ~MALIDP_SE_SCALING_EN;
+               malidp_hw_write(hwdev, val, se_control);
+               return;
+       }
+
+       hwdev->se_set_scaling_coeffs(hwdev, s, old_s);
+       val = malidp_hw_read(hwdev, se_control);
+       val |= MALIDP_SE_SCALING_EN | MALIDP_SE_ALPHA_EN;
+
+       val &= ~MALIDP_SE_ENH(MALIDP_SE_ENH_MASK);
+       val |= s->enhancer_enable ? MALIDP_SE_ENH(3) : 0;
+
+       val |= MALIDP_SE_RGBO_IF_EN;
+       malidp_hw_write(hwdev, val, se_control);
+
+       /* Set IN_SIZE & OUT_SIZE. */
+       val = MALIDP_SE_SET_V_SIZE(s->input_h) |
+             MALIDP_SE_SET_H_SIZE(s->input_w);
+       malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_IN_SIZE);
+       val = MALIDP_SE_SET_V_SIZE(s->output_h) |
+             MALIDP_SE_SET_H_SIZE(s->output_w);
+       malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_OUT_SIZE);
+
+       /* Set phase regs. */
+       malidp_hw_write(hwdev, s->h_init_phase, scr + MALIDP_SE_H_INIT_PH);
+       malidp_hw_write(hwdev, s->h_delta_phase, scr + MALIDP_SE_H_DELTA_PH);
+       malidp_hw_write(hwdev, s->v_init_phase, scr + MALIDP_SE_V_INIT_PH);
+       malidp_hw_write(hwdev, s->v_delta_phase, scr + MALIDP_SE_V_DELTA_PH);
+}
+
 /*
  * set the "config valid" bit and wait until the hardware acts on it
  */
@@ -66,10 +193,12 @@ static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
        struct drm_pending_vblank_event *event;
        struct drm_device *drm = state->dev;
        struct malidp_drm *malidp = drm->dev_private;
-       int ret = malidp_set_and_wait_config_valid(drm);
 
-       if (ret)
-               DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
+       if (malidp->crtc.enabled) {
+               /* only set config_valid if the CRTC is enabled */
+               if (malidp_set_and_wait_config_valid(drm))
+                       DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
+       }
 
        event = malidp->crtc.state->event;
        if (event) {
@@ -88,15 +217,30 @@ static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
 static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
 {
        struct drm_device *drm = state->dev;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *old_crtc_state;
+       int i;
+
+       pm_runtime_get_sync(drm->dev);
 
        drm_atomic_helper_commit_modeset_disables(drm, state);
-       drm_atomic_helper_commit_modeset_enables(drm, state);
+
+       for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+               malidp_atomic_commit_update_gamma(crtc, old_crtc_state);
+               malidp_atomic_commit_update_coloradj(crtc, old_crtc_state);
+               malidp_atomic_commit_se_config(crtc, old_crtc_state);
+       }
+
        drm_atomic_helper_commit_planes(drm, state, 0);
 
+       drm_atomic_helper_commit_modeset_enables(drm, state);
+
        malidp_atomic_commit_hw_done(state);
 
        drm_atomic_helper_wait_for_vblanks(drm, state);
 
+       pm_runtime_put(drm->dev);
+
        drm_atomic_helper_cleanup_planes(drm, state);
 }
 
@@ -277,8 +421,65 @@ static bool malidp_has_sufficient_address_space(const struct resource *res,
        return true;
 }
 
+static ssize_t core_id_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+       struct malidp_drm *malidp = drm->dev_private;
+
+       return snprintf(buf, PAGE_SIZE, "%08x\n", malidp->core_id);
+}
+
+DEVICE_ATTR_RO(core_id);
+
+static int malidp_init_sysfs(struct device *dev)
+{
+       int ret = device_create_file(dev, &dev_attr_core_id);
+
+       if (ret)
+               DRM_ERROR("failed to create device file for core_id\n");
+
+       return ret;
+}
+
+static void malidp_fini_sysfs(struct device *dev)
+{
+       device_remove_file(dev, &dev_attr_core_id);
+}
+
 #define MAX_OUTPUT_CHANNELS    3
 
+static int malidp_runtime_pm_suspend(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+       struct malidp_drm *malidp = drm->dev_private;
+       struct malidp_hw_device *hwdev = malidp->dev;
+
+       /* we can only suspend if the hardware is in config mode */
+       WARN_ON(!hwdev->in_config_mode(hwdev));
+
+       hwdev->pm_suspended = true;
+       clk_disable_unprepare(hwdev->mclk);
+       clk_disable_unprepare(hwdev->aclk);
+       clk_disable_unprepare(hwdev->pclk);
+
+       return 0;
+}
+
+static int malidp_runtime_pm_resume(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+       struct malidp_drm *malidp = drm->dev_private;
+       struct malidp_hw_device *hwdev = malidp->dev;
+
+       clk_prepare_enable(hwdev->pclk);
+       clk_prepare_enable(hwdev->aclk);
+       clk_prepare_enable(hwdev->mclk);
+       hwdev->pm_suspended = false;
+
+       return 0;
+}
+
 static int malidp_bind(struct device *dev)
 {
        struct resource *res;
@@ -307,7 +508,6 @@ static int malidp_bind(struct device *dev)
        memcpy(hwdev, of_device_get_match_data(dev), sizeof(*hwdev));
        malidp->dev = hwdev;
 
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        hwdev->regs = devm_ioremap_resource(dev, res);
        if (IS_ERR(hwdev->regs))
@@ -340,14 +540,17 @@ static int malidp_bind(struct device *dev)
                goto alloc_fail;
        }
 
-       /* Enable APB clock in order to get access to the registers */
-       clk_prepare_enable(hwdev->pclk);
-       /*
-        * Enable AXI clock and main clock so that prefetch can start once
-        * the registers are set
-        */
-       clk_prepare_enable(hwdev->aclk);
-       clk_prepare_enable(hwdev->mclk);
+       drm->dev_private = malidp;
+       dev_set_drvdata(dev, drm);
+
+       /* Enable power management */
+       pm_runtime_enable(dev);
+
+       /* Resume device to enable the clocks */
+       if (pm_runtime_enabled(dev))
+               pm_runtime_get_sync(dev);
+       else
+               malidp_runtime_pm_resume(dev);
 
        dev_id = of_match_device(malidp_drm_of_match, dev);
        if (!dev_id) {
@@ -376,6 +579,8 @@ static int malidp_bind(struct device *dev)
        DRM_INFO("found ARM Mali-DP%3x version r%dp%d\n", version >> 16,
                 (version >> 12) & 0xf, (version >> 8) & 0xf);
 
+       malidp->core_id = version;
+
        /* set the number of lines used for output of RGB data */
        ret = of_property_read_u8_array(dev->of_node,
                                        "arm,malidp-output-port-lines",
@@ -387,13 +592,15 @@ static int malidp_bind(struct device *dev)
                out_depth = (out_depth << 8) | (output_width[i] & 0xf);
        malidp_hw_write(hwdev, out_depth, hwdev->map.out_depth_base);
 
-       drm->dev_private = malidp;
-       dev_set_drvdata(dev, drm);
        atomic_set(&malidp->config_valid, 0);
        init_waitqueue_head(&malidp->wq);
 
        ret = malidp_init(drm);
        if (ret < 0)
+               goto query_hw_fail;
+
+       ret = malidp_init_sysfs(dev);
+       if (ret)
                goto init_fail;
 
        /* Set the CRTC's port so that the encoder component can find it */
@@ -416,6 +623,7 @@ static int malidp_bind(struct device *dev)
                DRM_ERROR("failed to initialise vblank\n");
                goto vblank_fail;
        }
+       pm_runtime_put(dev);
 
        drm_mode_config_reset(drm);
 
@@ -441,7 +649,9 @@ register_fail:
                drm_fbdev_cma_fini(malidp->fbdev);
                malidp->fbdev = NULL;
        }
+       drm_kms_helper_poll_fini(drm);
 fbdev_fail:
+       pm_runtime_get_sync(dev);
        drm_vblank_cleanup(drm);
 vblank_fail:
        malidp_se_irq_fini(drm);
@@ -452,14 +662,17 @@ irq_init_fail:
 bind_fail:
        of_node_put(malidp->crtc.port);
        malidp->crtc.port = NULL;
-       malidp_fini(drm);
 init_fail:
+       malidp_fini_sysfs(dev);
+       malidp_fini(drm);
+query_hw_fail:
+       pm_runtime_put(dev);
+       if (pm_runtime_enabled(dev))
+               pm_runtime_disable(dev);
+       else
+               malidp_runtime_pm_suspend(dev);
        drm->dev_private = NULL;
        dev_set_drvdata(dev, NULL);
-query_hw_fail:
-       clk_disable_unprepare(hwdev->mclk);
-       clk_disable_unprepare(hwdev->aclk);
-       clk_disable_unprepare(hwdev->pclk);
        drm_dev_unref(drm);
 alloc_fail:
        of_reserved_mem_device_release(dev);
@@ -471,7 +684,6 @@ static void malidp_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
        struct malidp_drm *malidp = drm->dev_private;
-       struct malidp_hw_device *hwdev = malidp->dev;
 
        drm_dev_unregister(drm);
        if (malidp->fbdev) {
@@ -479,18 +691,22 @@ static void malidp_unbind(struct device *dev)
                malidp->fbdev = NULL;
        }
        drm_kms_helper_poll_fini(drm);
+       pm_runtime_get_sync(dev);
+       drm_vblank_cleanup(drm);
        malidp_se_irq_fini(drm);
        malidp_de_irq_fini(drm);
-       drm_vblank_cleanup(drm);
        component_unbind_all(dev, drm);
        of_node_put(malidp->crtc.port);
        malidp->crtc.port = NULL;
+       malidp_fini_sysfs(dev);
        malidp_fini(drm);
+       pm_runtime_put(dev);
+       if (pm_runtime_enabled(dev))
+               pm_runtime_disable(dev);
+       else
+               malidp_runtime_pm_suspend(dev);
        drm->dev_private = NULL;
        dev_set_drvdata(dev, NULL);
-       clk_disable_unprepare(hwdev->mclk);
-       clk_disable_unprepare(hwdev->aclk);
-       clk_disable_unprepare(hwdev->pclk);
        drm_dev_unref(drm);
        of_reserved_mem_device_release(dev);
 }
@@ -533,11 +749,52 @@ static int malidp_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int __maybe_unused malidp_pm_suspend(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+       struct malidp_drm *malidp = drm->dev_private;
+
+       drm_kms_helper_poll_disable(drm);
+       console_lock();
+       drm_fbdev_cma_set_suspend(malidp->fbdev, 1);
+       console_unlock();
+       malidp->pm_state = drm_atomic_helper_suspend(drm);
+       if (IS_ERR(malidp->pm_state)) {
+               console_lock();
+               drm_fbdev_cma_set_suspend(malidp->fbdev, 0);
+               console_unlock();
+               drm_kms_helper_poll_enable(drm);
+               return PTR_ERR(malidp->pm_state);
+       }
+
+       return 0;
+}
+
+static int __maybe_unused malidp_pm_resume(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+       struct malidp_drm *malidp = drm->dev_private;
+
+       drm_atomic_helper_resume(drm, malidp->pm_state);
+       console_lock();
+       drm_fbdev_cma_set_suspend(malidp->fbdev, 0);
+       console_unlock();
+       drm_kms_helper_poll_enable(drm);
+
+       return 0;
+}
+
+static const struct dev_pm_ops malidp_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(malidp_pm_suspend, malidp_pm_resume) \
+       SET_RUNTIME_PM_OPS(malidp_runtime_pm_suspend, malidp_runtime_pm_resume, NULL)
+};
+
 static struct platform_driver malidp_platform_driver = {
        .probe          = malidp_platform_probe,
        .remove         = malidp_platform_remove,
        .driver = {
                .name = "mali-dp",
+               .pm = &malidp_pm_ops,
                .of_match_table = malidp_drm_of_match,
        },
 };
index dbc617c6e4ef35006fb40148b83e6776fab1ef41..040311ffcaecc84bf08ef2f64b88f03719bbde5f 100644 (file)
@@ -24,6 +24,8 @@ struct malidp_drm {
        struct drm_crtc crtc;
        wait_queue_head_t wq;
        atomic_t config_valid;
+       struct drm_atomic_state *pm_state;
+       u32 core_id;
 };
 
 #define crtc_to_malidp_device(x) container_of(x, struct malidp_drm, crtc)
@@ -47,6 +49,17 @@ struct malidp_plane_state {
 #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
 #define to_malidp_plane_state(x) container_of(x, struct malidp_plane_state, base)
 
+struct malidp_crtc_state {
+       struct drm_crtc_state base;
+       u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS];
+       u32 coloradj_coeffs[MALIDP_COLORADJ_NUM_COEFFS];
+       struct malidp_se_config scaler_config;
+       /* Bitfield of all the planes that have requested a scaled output. */
+       u8 scaled_planes_mask;
+};
+
+#define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base)
+
 int malidp_de_planes_init(struct drm_device *drm);
 void malidp_de_planes_destroy(struct drm_device *drm);
 int malidp_crtc_init(struct drm_device *drm);
index 9f5513006eeef8b4e54f6727b44b0e97562935d6..28360b8542f724de1d049884ae1b5dfa4a7b9b0e 100644 (file)
@@ -12,6 +12,7 @@
  * in an attempt to provide to the rest of the driver code a unified view
  */
 
+#include <linux/clk.h>
 #include <linux/types.h>
 #include <linux/io.h>
 #include <drm/drmP.h>
@@ -86,6 +87,80 @@ static const struct malidp_layer malidp550_layers[] = {
        { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE },
 };
 
+#define SE_N_SCALING_COEFFS    96
+static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = {
+       [MALIDP_UPSCALING_COEFFS - 1] = {
+               0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052,
+               0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f,
+               0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a,
+               0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40,
+               0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c,
+               0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5,
+               0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15,
+               0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5,
+               0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0,
+               0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6,
+               0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073,
+               0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001
+       },
+       [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = {
+               0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4,
+               0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c,
+               0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5,
+               0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8,
+               0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba,
+               0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20,
+               0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03,
+               0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d,
+               0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68,
+               0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f,
+               0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62,
+               0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f
+       },
+       [MALIDP_DOWNSCALING_2_COEFFS - 1] = {
+               0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9,
+               0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52,
+               0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158,
+               0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455,
+               0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e,
+               0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887,
+               0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5,
+               0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e,
+               0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d,
+               0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0,
+               0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf,
+               0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03
+       },
+       [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = {
+               0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3,
+               0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106,
+               0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280,
+               0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410,
+               0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533,
+               0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3,
+               0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566,
+               0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468,
+               0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4,
+               0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160,
+               0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f,
+               0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60
+       },
+       [MALIDP_DOWNSCALING_4_COEFFS - 1] = {
+               0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f,
+               0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff,
+               0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd,
+               0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374,
+               0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db,
+               0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a,
+               0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed,
+               0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397,
+               0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb,
+               0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233,
+               0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160,
+               0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9
+       },
+};
+
 #define MALIDP_DE_DEFAULT_PREFETCH_START       5
 
 static int malidp500_query_hw(struct malidp_hw_device *hwdev)
@@ -211,6 +286,88 @@ static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
        return w * drm_format_plane_cpp(fmt, 0) * 8;
 }
 
+static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev,
+                                          u32 direction,
+                                          u16 addr,
+                                          u8 coeffs_id)
+{
+       int i;
+       u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL;
+
+       malidp_hw_write(hwdev,
+                       direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK),
+                       scaling_control + MALIDP_SE_COEFFTAB_ADDR);
+       for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i)
+               malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA(
+                               dp500_se_scaling_coeffs[coeffs_id][i]),
+                               scaling_control + MALIDP_SE_COEFFTAB_DATA);
+}
+
+static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
+                                          struct malidp_se_config *se_config,
+                                          struct malidp_se_config *old_config)
+{
+       /* Get array indices into dp500_se_scaling_coeffs. */
+       u8 h = (u8)se_config->hcoeff - 1;
+       u8 v = (u8)se_config->vcoeff - 1;
+
+       if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) ||
+                   v >= ARRAY_SIZE(dp500_se_scaling_coeffs)))
+               return -EINVAL;
+
+       if ((h == v) && (se_config->hcoeff != old_config->hcoeff ||
+                        se_config->vcoeff != old_config->vcoeff)) {
+               malidp500_se_write_pp_coefftab(hwdev,
+                                              (MALIDP_SE_V_COEFFTAB |
+                                               MALIDP_SE_H_COEFFTAB),
+                                              0, v);
+       } else {
+               if (se_config->vcoeff != old_config->vcoeff)
+                       malidp500_se_write_pp_coefftab(hwdev,
+                                                      MALIDP_SE_V_COEFFTAB,
+                                                      0, v);
+               if (se_config->hcoeff != old_config->hcoeff)
+                       malidp500_se_write_pp_coefftab(hwdev,
+                                                      MALIDP_SE_H_COEFFTAB,
+                                                      0, h);
+       }
+
+       return 0;
+}
+
+static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
+                                  struct malidp_se_config *se_config,
+                                  struct videomode *vm)
+{
+       unsigned long mclk;
+       unsigned long pxlclk = vm->pixelclock; /* Hz */
+       unsigned long htotal = vm->hactive + vm->hfront_porch +
+                              vm->hback_porch + vm->hsync_len;
+       unsigned long input_size = se_config->input_w * se_config->input_h;
+       unsigned long a = 10;
+       long ret;
+
+       /*
+        * mclk = max(a, 1.5) * pxlclk
+        *
+        * To avoid float calculaiton, using 15 instead of 1.5 and div by
+        * 10 to get mclk.
+        */
+       if (se_config->scale_enable) {
+               a = 15 * input_size / (htotal * se_config->output_h);
+               if (a < 15)
+                       a = 15;
+       }
+       mclk = a * pxlclk / 10;
+       ret = clk_get_rate(hwdev->mclk);
+       if (ret < mclk) {
+               DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
+                                mclk / 1000);
+               return -EINVAL;
+       }
+       return ret;
+}
+
 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
 {
        u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
@@ -384,6 +541,53 @@ static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
        return w * bytes_per_col;
 }
 
+static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev,
+                                          struct malidp_se_config *se_config,
+                                          struct malidp_se_config *old_config)
+{
+       u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) |
+                  MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK);
+       u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) |
+                       MALIDP550_SE_CTL_HCSEL(se_config->hcoeff);
+
+       malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL);
+       malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL);
+       return 0;
+}
+
+static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
+                                  struct malidp_se_config *se_config,
+                                  struct videomode *vm)
+{
+       unsigned long mclk;
+       unsigned long pxlclk = vm->pixelclock;
+       unsigned long htotal = vm->hactive + vm->hfront_porch +
+                              vm->hback_porch + vm->hsync_len;
+       unsigned long numerator = 1, denominator = 1;
+       long ret;
+
+       if (se_config->scale_enable) {
+               numerator = max(se_config->input_w, se_config->output_w) *
+                           se_config->input_h;
+               numerator += se_config->output_w *
+                            (se_config->output_h -
+                             min(se_config->input_h, se_config->output_h));
+               denominator = (htotal - 2) * se_config->output_h;
+       }
+
+       /* mclk can't be slower than pxlclk. */
+       if (numerator < denominator)
+               numerator = denominator = 1;
+       mclk = (pxlclk * numerator) / denominator;
+       ret = clk_get_rate(hwdev->mclk);
+       if (ret < mclk) {
+               DRM_DEBUG_DRIVER("mclk requirement of %lu kHz can't be met.\n",
+                                mclk / 1000);
+               return -EINVAL;
+       }
+       return ret;
+}
+
 static int malidp650_query_hw(struct malidp_hw_device *hwdev)
 {
        u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID);
@@ -415,6 +619,7 @@ static int malidp650_query_hw(struct malidp_hw_device *hwdev)
 const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
        [MALIDP_500] = {
                .map = {
+                       .coeffs_base = MALIDP500_COEFFS_BASE,
                        .se_base = MALIDP500_SE_BASE,
                        .dc_base = MALIDP500_DC_BASE,
                        .out_depth_base = MALIDP500_OUTPUT_DEPTH,
@@ -447,10 +652,13 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
                .set_config_valid = malidp500_set_config_valid,
                .modeset = malidp500_modeset,
                .rotmem_required = malidp500_rotmem_required,
+               .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs,
+               .se_calc_mclk = malidp500_se_calc_mclk,
                .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
        },
        [MALIDP_550] = {
                .map = {
+                       .coeffs_base = MALIDP550_COEFFS_BASE,
                        .se_base = MALIDP550_SE_BASE,
                        .dc_base = MALIDP550_DC_BASE,
                        .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
@@ -481,10 +689,13 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
                .set_config_valid = malidp550_set_config_valid,
                .modeset = malidp550_modeset,
                .rotmem_required = malidp550_rotmem_required,
+               .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
+               .se_calc_mclk = malidp550_se_calc_mclk,
                .features = 0,
        },
        [MALIDP_650] = {
                .map = {
+                       .coeffs_base = MALIDP550_COEFFS_BASE,
                        .se_base = MALIDP550_SE_BASE,
                        .dc_base = MALIDP550_DC_BASE,
                        .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
@@ -516,6 +727,8 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
                .set_config_valid = malidp550_set_config_valid,
                .modeset = malidp550_modeset,
                .rotmem_required = malidp550_rotmem_required,
+               .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
+               .se_calc_mclk = malidp550_se_calc_mclk,
                .features = 0,
        },
 };
index 00974b59407df59915c5751d5845228d040f91b7..849ad9a30c3af4b31e98526b954e2b0819275534 100644 (file)
@@ -61,12 +61,34 @@ struct malidp_layer {
        u16 stride_offset;      /* Offset to the first stride register. */
 };
 
+enum malidp_scaling_coeff_set {
+       MALIDP_UPSCALING_COEFFS = 1,
+       MALIDP_DOWNSCALING_1_5_COEFFS = 2,
+       MALIDP_DOWNSCALING_2_COEFFS = 3,
+       MALIDP_DOWNSCALING_2_75_COEFFS = 4,
+       MALIDP_DOWNSCALING_4_COEFFS = 5,
+};
+
+struct malidp_se_config {
+       u8 scale_enable : 1;
+       u8 enhancer_enable : 1;
+       u8 hcoeff : 3;
+       u8 vcoeff : 3;
+       u8 plane_src_id;
+       u16 input_w, input_h;
+       u16 output_w, output_h;
+       u32 h_init_phase, h_delta_phase;
+       u32 v_init_phase, v_delta_phase;
+};
+
 /* regmap features */
 #define MALIDP_REGMAP_HAS_CLEARIRQ     (1 << 0)
 
 struct malidp_hw_regmap {
        /* address offset of the DE register bank */
        /* is always 0x0000 */
+       /* address offset of the DE coefficients registers */
+       const u16 coeffs_base;
        /* address offset of the SE registers bank */
        const u16 se_base;
        /* address offset of the DC registers bank */
@@ -151,11 +173,22 @@ struct malidp_hw_device {
         */
        int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt);
 
+       int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
+                                    struct malidp_se_config *se_config,
+                                    struct malidp_se_config *old_config);
+
+       long (*se_calc_mclk)(struct malidp_hw_device *hwdev,
+                            struct malidp_se_config *se_config,
+                            struct videomode *vm);
+
        u8 features;
 
        u8 min_line_size;
        u16 max_line_size;
 
+       /* track the device PM state */
+       bool pm_suspended;
+
        /* size of memory used for rotating layers, up to two banks available */
        u32 rotation_memory[2];
 };
@@ -173,12 +206,14 @@ extern const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES];
 
 static inline u32 malidp_hw_read(struct malidp_hw_device *hwdev, u32 reg)
 {
+       WARN_ON(hwdev->pm_suspended);
        return readl(hwdev->regs + reg);
 }
 
 static inline void malidp_hw_write(struct malidp_hw_device *hwdev,
                                   u32 value, u32 reg)
 {
+       WARN_ON(hwdev->pm_suspended);
        writel(value, hwdev->regs + reg);
 }
 
@@ -243,6 +278,47 @@ static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
        return !(pitch & (hwdev->map.bus_align_bytes - 1));
 }
 
+/* U16.16 */
+#define FP_1_00000     0x00010000      /* 1.0 */
+#define FP_0_66667     0x0000AAAA      /* 0.6667 = 1/1.5 */
+#define FP_0_50000     0x00008000      /* 0.5 = 1/2 */
+#define FP_0_36363     0x00005D17      /* 0.36363 = 1/2.75 */
+#define FP_0_25000     0x00004000      /* 0.25 = 1/4 */
+
+static inline enum malidp_scaling_coeff_set
+malidp_se_select_coeffs(u32 upscale_factor)
+{
+       return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS :
+              (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS :
+              (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS :
+              (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS :
+              MALIDP_DOWNSCALING_4_COEFFS;
+}
+
+#undef FP_0_25000
+#undef FP_0_36363
+#undef FP_0_50000
+#undef FP_0_66667
+#undef FP_1_00000
+
+static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
+{
+       static const s32 enhancer_coeffs[] = {
+               -8, -8, -8, -8, 128, -8, -8, -8, -8
+       };
+       u32 val = MALIDP_SE_SET_ENH_LIMIT_LOW(MALIDP_SE_ENH_LOW_LEVEL) |
+                 MALIDP_SE_SET_ENH_LIMIT_HIGH(MALIDP_SE_ENH_HIGH_LEVEL);
+       u32 image_enh = hwdev->map.se_base +
+                       ((hwdev->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ?
+                        0x10 : 0xC) + MALIDP_SE_IMAGE_ENH;
+       u32 enh_coeffs = image_enh + MALIDP_SE_ENH_COEFF0;
+       int i;
+
+       malidp_hw_write(hwdev, val, image_enh);
+       for (i = 0; i < ARRAY_SIZE(enhancer_coeffs); ++i)
+               malidp_hw_write(hwdev, enhancer_coeffs[i], enh_coeffs + i * 4);
+}
+
 /*
  * background color components are defined as 12bits values,
  * they will be shifted right when stored on hardware that
@@ -252,4 +328,9 @@ static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
 #define MALIDP_BGND_COLOR_G            0x000
 #define MALIDP_BGND_COLOR_B            0x000
 
+#define MALIDP_COLORADJ_NUM_COEFFS     12
+#define MALIDP_COEFFTAB_NUM_COEFFS     64
+
+#define MALIDP_GAMMA_LUT_SIZE          4096
+
 #endif  /* __MALIDP_HW_H__ */
index d5aec082294cbdde5a19986a5b1908aef974bb19..814fda23ceade6159fab04455facbbff35ba65e7 100644 (file)
@@ -16,6 +16,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_print.h>
 
 #include "malidp_hw.h"
 #include "malidp_drv.h"
@@ -24,6 +25,9 @@
 #define MALIDP_LAYER_FORMAT            0x000
 #define MALIDP_LAYER_CONTROL           0x004
 #define   LAYER_ENABLE                 (1 << 0)
+#define   LAYER_FLOWCFG_MASK           7
+#define   LAYER_FLOWCFG(x)             (((x) & LAYER_FLOWCFG_MASK) << 1)
+#define     LAYER_FLOWCFG_SCALE_SE     3
 #define   LAYER_ROT_OFFSET             8
 #define   LAYER_H_FLIP                 (1 << 10)
 #define   LAYER_V_FLIP                 (1 << 11)
@@ -60,6 +64,27 @@ static void malidp_de_plane_destroy(struct drm_plane *plane)
        devm_kfree(plane->dev->dev, mp);
 }
 
+/*
+ * Replicate what the default ->reset hook does: free the state pointer and
+ * allocate a new empty object. We just need enough space to store
+ * a malidp_plane_state instead of a drm_plane_state.
+ */
+static void malidp_plane_reset(struct drm_plane *plane)
+{
+       struct malidp_plane_state *state = to_malidp_plane_state(plane->state);
+
+       if (state)
+               __drm_atomic_helper_plane_destroy_state(&state->base);
+       kfree(state);
+       plane->state = NULL;
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (state) {
+               state->base.plane = plane;
+               state->base.rotation = DRM_ROTATE_0;
+               plane->state = &state->base;
+       }
+}
+
 static struct
 drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
 {
@@ -90,26 +115,71 @@ static void malidp_destroy_plane_state(struct drm_plane *plane,
        kfree(m_state);
 }
 
+static void malidp_plane_atomic_print_state(struct drm_printer *p,
+                                           const struct drm_plane_state *state)
+{
+       struct malidp_plane_state *ms = to_malidp_plane_state(state);
+
+       drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
+       drm_printf(p, "\tformat_id=%u\n", ms->format);
+       drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
+}
+
 static const struct drm_plane_funcs malidp_de_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .set_property = drm_atomic_helper_plane_set_property,
        .destroy = malidp_de_plane_destroy,
-       .reset = drm_atomic_helper_plane_reset,
+       .reset = malidp_plane_reset,
        .atomic_duplicate_state = malidp_duplicate_plane_state,
        .atomic_destroy_state = malidp_destroy_plane_state,
+       .atomic_print_state = malidp_plane_atomic_print_state,
 };
 
+static int malidp_se_check_scaling(struct malidp_plane *mp,
+                                  struct drm_plane_state *state)
+{
+       struct drm_crtc_state *crtc_state =
+               drm_atomic_get_existing_crtc_state(state->state, state->crtc);
+       struct malidp_crtc_state *mc;
+       struct drm_rect clip = { 0 };
+       u32 src_w, src_h;
+       int ret;
+
+       if (!crtc_state)
+               return -EINVAL;
+
+       clip.x2 = crtc_state->adjusted_mode.hdisplay;
+       clip.y2 = crtc_state->adjusted_mode.vdisplay;
+       ret = drm_plane_helper_check_state(state, &clip, 0, INT_MAX, true, true);
+       if (ret)
+               return ret;
+
+       src_w = state->src_w >> 16;
+       src_h = state->src_h >> 16;
+       if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) {
+               /* Scaling not necessary for this plane. */
+               mc->scaled_planes_mask &= ~(mp->layer->id);
+               return 0;
+       }
+
+       if (mp->layer->id & (DE_SMART | DE_GRAPHICS2))
+               return -EINVAL;
+
+       mc = to_malidp_crtc_state(crtc_state);
+
+       mc->scaled_planes_mask |= mp->layer->id;
+       /* Defer scaling requirements calculation to the crtc check. */
+       return 0;
+}
+
 static int malidp_de_plane_check(struct drm_plane *plane,
                                 struct drm_plane_state *state)
 {
        struct malidp_plane *mp = to_malidp_plane(plane);
        struct malidp_plane_state *ms = to_malidp_plane_state(state);
-       struct drm_crtc_state *crtc_state;
        struct drm_framebuffer *fb;
-       struct drm_rect clip = { 0 };
        int i, ret;
-       u32 src_w, src_h;
 
        if (!state->crtc || !state->fb)
                return 0;
@@ -130,9 +200,6 @@ static int malidp_de_plane_check(struct drm_plane *plane,
                }
        }
 
-       src_w = state->src_w >> 16;
-       src_h = state->src_h >> 16;
-
        if ((state->crtc_w > mp->hwdev->max_line_size) ||
            (state->crtc_h > mp->hwdev->max_line_size) ||
            (state->crtc_w < mp->hwdev->min_line_size) ||
@@ -149,22 +216,16 @@ static int malidp_de_plane_check(struct drm_plane *plane,
            (state->fb->pitches[1] != state->fb->pitches[2]))
                return -EINVAL;
 
+       ret = malidp_se_check_scaling(mp, state);
+       if (ret)
+               return ret;
+
        /* packed RGB888 / BGR888 can't be rotated or flipped */
        if (state->rotation != DRM_ROTATE_0 &&
            (fb->format->format == DRM_FORMAT_RGB888 ||
             fb->format->format == DRM_FORMAT_BGR888))
                return -EINVAL;
 
-       crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc);
-       clip.x2 = crtc_state->adjusted_mode.hdisplay;
-       clip.y2 = crtc_state->adjusted_mode.vdisplay;
-       ret = drm_plane_helper_check_state(state, &clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          true, true);
-       if (ret)
-               return ret;
-
        ms->rotmem_size = 0;
        if (state->rotation & MALIDP_ROTATED_MASK) {
                int val;
@@ -269,6 +330,16 @@ static void malidp_de_plane_update(struct drm_plane *plane,
        val &= ~LAYER_COMP_MASK;
        val |= LAYER_COMP_PIXEL;
 
+       val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
+       if (plane->state->crtc) {
+               struct malidp_crtc_state *m =
+                       to_malidp_crtc_state(plane->state->crtc->state);
+
+               if (m->scaler_config.scale_enable &&
+                   m->scaler_config.plane_src_id == mp->layer->id)
+                       val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE);
+       }
+
        /* set the 'enable layer' bit */
        val |= LAYER_ENABLE;
 
@@ -281,7 +352,8 @@ static void malidp_de_plane_disable(struct drm_plane *plane,
 {
        struct malidp_plane *mp = to_malidp_plane(plane);
 
-       malidp_hw_clearbits(mp->hwdev, LAYER_ENABLE,
+       malidp_hw_clearbits(mp->hwdev,
+                           LAYER_ENABLE | LAYER_FLOWCFG(LAYER_FLOWCFG_MASK),
                            mp->layer->base + MALIDP_LAYER_CONTROL);
 }
 
index b816067a65c5727ab120000c5d5d080e022fee2c..2039f857f77d54766b9c07f0fadbff487053ef95 100644 (file)
@@ -63,6 +63,8 @@
 
 /* bit masks that are common between products */
 #define   MALIDP_CFG_VALID             (1 << 0)
+#define   MALIDP_DISP_FUNC_GAMMA       (1 << 0)
+#define   MALIDP_DISP_FUNC_CADJ                (1 << 4)
 #define   MALIDP_DISP_FUNC_ILACED      (1 << 8)
 
 /* register offsets for IRQ management */
 
 #define MALIDP_PRODUCT_ID(__core_id) ((u32)(__core_id) >> 16)
 
+/* register offsets relative to MALIDP5x0_COEFFS_BASE */
+#define MALIDP_COLOR_ADJ_COEF          0x00000
+#define MALIDP_COEF_TABLE_ADDR         0x00030
+#define MALIDP_COEF_TABLE_DATA         0x00034
+
+/* Scaling engine registers and masks. */
+#define   MALIDP_SE_SCALING_EN                 (1 << 0)
+#define   MALIDP_SE_ALPHA_EN                   (1 << 1)
+#define   MALIDP_SE_ENH_MASK                   3
+#define   MALIDP_SE_ENH(x)                     (((x) & MALIDP_SE_ENH_MASK) << 2)
+#define   MALIDP_SE_RGBO_IF_EN                 (1 << 4)
+#define   MALIDP550_SE_CTL_SEL_MASK            7
+#define   MALIDP550_SE_CTL_VCSEL(x) \
+               (((x) & MALIDP550_SE_CTL_SEL_MASK) << 20)
+#define   MALIDP550_SE_CTL_HCSEL(x) \
+               (((x) & MALIDP550_SE_CTL_SEL_MASK) << 16)
+
+/* Blocks with offsets from SE_CONTROL register. */
+#define MALIDP_SE_LAYER_CONTROL                        0x14
+#define   MALIDP_SE_L0_IN_SIZE                 0x00
+#define   MALIDP_SE_L0_OUT_SIZE                        0x04
+#define   MALIDP_SE_SET_V_SIZE(x)              (((x) & 0x1fff) << 16)
+#define   MALIDP_SE_SET_H_SIZE(x)              (((x) & 0x1fff) << 0)
+#define MALIDP_SE_SCALING_CONTROL              0x24
+#define   MALIDP_SE_H_INIT_PH                  0x00
+#define   MALIDP_SE_H_DELTA_PH                 0x04
+#define   MALIDP_SE_V_INIT_PH                  0x08
+#define   MALIDP_SE_V_DELTA_PH                 0x0c
+#define   MALIDP_SE_COEFFTAB_ADDR              0x10
+#define     MALIDP_SE_COEFFTAB_ADDR_MASK       0x7f
+#define     MALIDP_SE_V_COEFFTAB               (1 << 8)
+#define     MALIDP_SE_H_COEFFTAB               (1 << 9)
+#define     MALIDP_SE_SET_V_COEFFTAB_ADDR(x) \
+               (MALIDP_SE_V_COEFFTAB | ((x) & MALIDP_SE_COEFFTAB_ADDR_MASK))
+#define     MALIDP_SE_SET_H_COEFFTAB_ADDR(x) \
+               (MALIDP_SE_H_COEFFTAB | ((x) & MALIDP_SE_COEFFTAB_ADDR_MASK))
+#define   MALIDP_SE_COEFFTAB_DATA              0x14
+#define     MALIDP_SE_COEFFTAB_DATA_MASK       0x3fff
+#define     MALIDP_SE_SET_COEFFTAB_DATA(x) \
+               ((x) & MALIDP_SE_COEFFTAB_DATA_MASK)
+/* Enhance coeffents reigster offset */
+#define MALIDP_SE_IMAGE_ENH                    0x3C
+/* ENH_LIMITS offset 0x0 */
+#define     MALIDP_SE_ENH_LOW_LEVEL            24
+#define     MALIDP_SE_ENH_HIGH_LEVEL           63
+#define     MALIDP_SE_ENH_LIMIT_MASK           0xfff
+#define     MALIDP_SE_SET_ENH_LIMIT_LOW(x) \
+               ((x) & MALIDP_SE_ENH_LIMIT_MASK)
+#define     MALIDP_SE_SET_ENH_LIMIT_HIGH(x) \
+               (((x) & MALIDP_SE_ENH_LIMIT_MASK) << 16)
+#define   MALIDP_SE_ENH_COEFF0                 0x04
+
 /* register offsets and bits specific to DP500 */
 #define MALIDP500_ADDR_SPACE_SIZE      0x01000
 #define MALIDP500_DC_BASE              0x00000
 #define MALIDP500_COLOR_ADJ_COEF       0x00078
 #define MALIDP500_COEF_TABLE_ADDR      0x000a8
 #define MALIDP500_COEF_TABLE_DATA      0x000ac
+
+/*
+ * The YUV2RGB coefficients on the DP500 are not in the video layer's register
+ * block. They belong in a separate block above the layer's registers, hence
+ * the negative offset.
+ */
+#define MALIDP500_LV_YUV2RGB           ((s16)(-0xB8))
+/*
+ * To match DP550/650, the start of the coeffs registers is
+ * at COLORADJ_COEFF0 instead of at YUV_RGB_COEF1.
+ */
+#define MALIDP500_COEFFS_BASE          0x00078
 #define MALIDP500_DE_LV_BASE           0x00100
 #define MALIDP500_DE_LV_PTR_BASE       0x00124
 #define MALIDP500_DE_LG1_BASE          0x00200
 #define MALIDP500_DE_LG2_BASE          0x00300
 #define MALIDP500_DE_LG2_PTR_BASE      0x0031c
 #define MALIDP500_SE_BASE              0x00c00
+#define MALIDP500_SE_CONTROL           0x00c0c
 #define MALIDP500_SE_PTR_BASE          0x00e0c
 #define MALIDP500_DC_IRQ_BASE          0x00f00
 #define MALIDP500_CONFIG_VALID         0x00f00
 #define MALIDP550_DE_DISP_SIDEBAND     0x00040
 #define MALIDP550_DE_BGND_COLOR                0x00044
 #define MALIDP550_DE_OUTPUT_DEPTH      0x0004c
-#define MALIDP550_DE_COLOR_COEF                0x00050
-#define MALIDP550_DE_COEF_TABLE_ADDR   0x00080
-#define MALIDP550_DE_COEF_TABLE_DATA   0x00084
+#define MALIDP550_COEFFS_BASE          0x00050
 #define MALIDP550_DE_LV1_BASE          0x00100
 #define MALIDP550_DE_LV1_PTR_BASE      0x00124
 #define MALIDP550_DE_LV2_BASE          0x00200
 #define MALIDP550_DE_LS_PTR_BASE       0x0042c
 #define MALIDP550_DE_PERF_BASE         0x00500
 #define MALIDP550_SE_BASE              0x08000
+#define MALIDP550_SE_CONTROL           0x08010
 #define MALIDP550_DC_BASE              0x0c000
 #define MALIDP550_DC_CONTROL           0x0c010
 #define   MALIDP550_DC_CONFIG_REQ      (1 << 16)
index 1597458d884e26d7a77e75baae3f8dd2343e4cf1..d6c2a5d190ebf7e73d30890448d6c876b5d96355 100644 (file)
@@ -529,10 +529,10 @@ static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = {
        .map_dma_buf    = armada_gem_prime_map_dma_buf,
        .unmap_dma_buf  = armada_gem_prime_unmap_dma_buf,
        .release        = drm_gem_dmabuf_release,
-       .kmap_atomic    = armada_gem_dmabuf_no_kmap,
-       .kunmap_atomic  = armada_gem_dmabuf_no_kunmap,
-       .kmap           = armada_gem_dmabuf_no_kmap,
-       .kunmap         = armada_gem_dmabuf_no_kunmap,
+       .map_atomic     = armada_gem_dmabuf_no_kmap,
+       .unmap_atomic   = armada_gem_dmabuf_no_kunmap,
+       .map            = armada_gem_dmabuf_no_kmap,
+       .unmap          = armada_gem_dmabuf_no_kunmap,
        .mmap           = armada_gem_dmabuf_mmap,
 };
 
index f987b4572d4a9c3d486c6bff49c9bad2e03abbe5..65a3bd7a0c00dbf919d46e6d464d8bce8a5ccfd1 100644 (file)
@@ -221,7 +221,8 @@ err_encoder_cleanup:
 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
        struct device_node *remote;
-       int ret, endpoint = 0;
+       int ret = -ENODEV;
+       int endpoint = 0;
 
        while (true) {
                /* Loop thru possible multiple connections to the output */
@@ -236,7 +237,5 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
                        return ret;
        }
 
-       if (!endpoint)
-               return -ENODEV;
        return ret;
 }
index 3bc856cc6daa633462f04ebce1476461d6c550e0..4e1f54a675d8def6c5f3f2ae8e261d802c17ccb2 100644 (file)
@@ -1947,6 +1947,20 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
        return 0;
 }
 
+static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
+                                     const struct drm_display_mode *orig_mode,
+                                     struct drm_display_mode *mode)
+{
+       struct dw_hdmi *hdmi = bridge->driver_private;
+       struct drm_connector *connector = &hdmi->connector;
+       enum drm_mode_status status;
+
+       status = dw_hdmi_connector_mode_valid(connector, mode);
+       if (status != MODE_OK)
+               return false;
+       return true;
+}
+
 static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
                                    struct drm_display_mode *orig_mode,
                                    struct drm_display_mode *mode)
@@ -1988,6 +2002,7 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
        .enable = dw_hdmi_bridge_enable,
        .disable = dw_hdmi_bridge_disable,
        .mode_set = dw_hdmi_bridge_mode_set,
+       .mode_fixup = dw_hdmi_bridge_mode_fixup,
 };
 
 static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
index 9fb65b736a90f132591e3b1722fd8f533696e3f6..954eb848b5e2125741fa025bc8892ba720a8aef7 100644 (file)
@@ -403,10 +403,10 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
        .map_dma_buf = drm_gem_map_dma_buf,
        .unmap_dma_buf = drm_gem_unmap_dma_buf,
        .release = drm_gem_dmabuf_release,
-       .kmap = drm_gem_dmabuf_kmap,
-       .kmap_atomic = drm_gem_dmabuf_kmap_atomic,
-       .kunmap = drm_gem_dmabuf_kunmap,
-       .kunmap_atomic = drm_gem_dmabuf_kunmap_atomic,
+       .map = drm_gem_dmabuf_kmap,
+       .map_atomic = drm_gem_dmabuf_kmap_atomic,
+       .unmap = drm_gem_dmabuf_kunmap,
+       .unmap_atomic = drm_gem_dmabuf_kunmap_atomic,
        .mmap = drm_gem_dmabuf_mmap,
        .vmap = drm_gem_dmabuf_vmap,
        .vunmap = drm_gem_dmabuf_vunmap,
index 3feef0659940c97025ce69349bda0c41f807c18f..3e88fa24eab3d382b037a873c6849fe32ead1d46 100644 (file)
@@ -476,7 +476,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
            drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
                list_for_each_entry(prop_enum, &property->enum_list, head) {
                        enum_count++;
-                       if (out_resp->count_enum_blobs <= enum_count)
+                       if (out_resp->count_enum_blobs < enum_count)
                                continue;
 
                        if (copy_to_user(&enum_ptr[copied].value,
index 4f587058a3aa566943a6278b8681a0692d56b6c4..9a9c407178018a7521577cf04f12914facf73d4c 100644 (file)
@@ -1333,7 +1333,7 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
        if (!fence) {
                event_free(gpu, event);
                ret = -ENOMEM;
-               goto out_pm_put;
+               goto out_unlock;
        }
 
        gpu->event[event].fence = fence;
@@ -1373,6 +1373,7 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
        hangcheck_timer_reset(gpu);
        ret = 0;
 
+out_unlock:
        mutex_unlock(&gpu->lock);
 
 out_pm_put:
index b7d7721e72faddc2a2d4fc76d69d795b8053cfad..40af17ec6312533d4080cc1581faa4683a0405b9 100644 (file)
@@ -285,9 +285,6 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
 {
        int ret;
 
-       if (vgpu->failsafe)
-               return 0;
-
        if (WARN_ON(bytes > 4))
                return -EINVAL;
 
index dc9aef3e92d462ca76c010f140302bb388e14844..dca989eb2d42ed48f6c13c15fe9d3f8a9cbfaab2 100644 (file)
@@ -774,7 +774,8 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)
                        _EL_OFFSET_STATUS_PTR);
 
        ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg);
-       ctx_status_ptr.read_ptr = ctx_status_ptr.write_ptr = 0x7;
+       ctx_status_ptr.read_ptr = 0;
+       ctx_status_ptr.write_ptr = 0x7;
        vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
 }
 
index 933a7c211a1c29ab77357119e37b0de2bb3dd521..dce8d15f706f58b4cf1019ddc1d5b609c903980c 100644 (file)
@@ -75,11 +75,11 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
        struct gvt_firmware_header *h;
        void *firmware;
        void *p;
-       unsigned long size;
+       unsigned long size, crc32_start;
        int i;
        int ret;
 
-       size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1;
+       size = sizeof(*h) + info->mmio_size + info->cfg_space_size;
        firmware = vzalloc(size);
        if (!firmware)
                return -ENOMEM;
@@ -112,6 +112,9 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
 
        memcpy(gvt->firmware.mmio, p, info->mmio_size);
 
+       crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4;
+       h->crc32 = crc32_le(0, firmware + crc32_start, size - crc32_start);
+
        firmware_attr.size = size;
        firmware_attr.private = firmware;
 
@@ -234,7 +237,7 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt)
 
        firmware->mmio = mem;
 
-       sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state",
+       sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%02x.golden_hw_state",
                 GVT_FIRMWARE_PATH, pdev->vendor, pdev->device,
                 pdev->revision);
 
index 0f3a98865a58265815831814590deaeebb2ec032..7dea5e5d556793c4cbf0fbb974819752ae211a69 100644 (file)
@@ -52,6 +52,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
        .vgpu_create = intel_gvt_create_vgpu,
        .vgpu_destroy = intel_gvt_destroy_vgpu,
        .vgpu_reset = intel_gvt_reset_vgpu,
+       .vgpu_activate = intel_gvt_activate_vgpu,
+       .vgpu_deactivate = intel_gvt_deactivate_vgpu,
 };
 
 /**
index 806da96b6a92ab83fec739cfb6e8cb5afb2110db..930732e5c7806d8970183f5d389c52d388bf2fc3 100644 (file)
@@ -395,7 +395,8 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
 void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
                                 unsigned int engine_mask);
 void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu);
-
+void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu);
+void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu);
 
 /* validating GM functions */
 #define vgpu_gmadr_is_aperture(vgpu, gmadr) \
@@ -462,6 +463,8 @@ struct intel_gvt_ops {
                                struct intel_vgpu_type *);
        void (*vgpu_destroy)(struct intel_vgpu *);
        void (*vgpu_reset)(struct intel_vgpu *);
+       void (*vgpu_activate)(struct intel_vgpu *);
+       void (*vgpu_deactivate)(struct intel_vgpu *);
 };
 
 
index 42ff7ffb6066526451e6b615ddeac0608bdc23b1..1ae0b4083ce10b933e877ab7cafdd41b543a2b60 100644 (file)
@@ -546,6 +546,8 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        if (ret)
                goto undo_group;
 
+       intel_gvt_ops->vgpu_activate(vgpu);
+
        atomic_set(&vgpu->vdev.released, 0);
        return ret;
 
@@ -571,6 +573,8 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
        if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1))
                return;
 
+       intel_gvt_ops->vgpu_deactivate(vgpu);
+
        ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_IOMMU_NOTIFY,
                                        &vgpu->vdev.iommu_notifier);
        WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret);
index 6ba02525e90598f74b67bc7b1144511efef55820..6e3cbd8caec26c029e162c865346a8e0ac28b001 100644 (file)
@@ -196,20 +196,34 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
 }
 
 /**
- * intel_gvt_destroy_vgpu - destroy a virtual GPU
+ * intel_gvt_active_vgpu - activate a virtual GPU
  * @vgpu: virtual GPU
  *
- * This function is called when user wants to destroy a virtual GPU.
+ * This function is called when user wants to activate a virtual GPU.
  *
  */
-void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
+void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu)
+{
+       mutex_lock(&vgpu->gvt->lock);
+       vgpu->active = true;
+       mutex_unlock(&vgpu->gvt->lock);
+}
+
+/**
+ * intel_gvt_deactive_vgpu - deactivate a virtual GPU
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to deactivate a virtual GPU.
+ * All virtual GPU runtime information will be destroyed.
+ *
+ */
+void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu)
 {
        struct intel_gvt *gvt = vgpu->gvt;
 
        mutex_lock(&gvt->lock);
 
        vgpu->active = false;
-       idr_remove(&gvt->vgpu_idr, vgpu->id);
 
        if (atomic_read(&vgpu->running_workload_num)) {
                mutex_unlock(&gvt->lock);
@@ -218,6 +232,26 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
        }
 
        intel_vgpu_stop_schedule(vgpu);
+
+       mutex_unlock(&gvt->lock);
+}
+
+/**
+ * intel_gvt_destroy_vgpu - destroy a virtual GPU
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to destroy a virtual GPU.
+ *
+ */
+void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+
+       mutex_lock(&gvt->lock);
+
+       WARN(vgpu->active, "vGPU is still active!\n");
+
+       idr_remove(&gvt->vgpu_idr, vgpu->id);
        intel_vgpu_clean_sched_policy(vgpu);
        intel_vgpu_clean_gvt_context(vgpu);
        intel_vgpu_clean_execlist(vgpu);
@@ -349,7 +383,6 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
        if (ret)
                goto out_clean_shadow_ctx;
 
-       vgpu->active = true;
        mutex_unlock(&gvt->lock);
 
        return vgpu;
index 1aa26d5f1779db8a74baf8fe8c371e9835dbe599..3036d4835b0fa7a3b366a31d0b6ed18fc7889ae1 100644 (file)
@@ -1469,8 +1469,6 @@ static int i915_drm_suspend(struct drm_device *dev)
                goto out;
        }
 
-       intel_guc_suspend(dev_priv);
-
        intel_display_suspend(dev);
 
        intel_dp_mst_suspend(dev);
index 28b92017b1eafc1afe792c93274718e194ffc200..532a577ff7a14e8f56613f605bb515833f7cc615 100644 (file)
@@ -4456,6 +4456,8 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)
        i915_gem_context_lost(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
+       intel_guc_suspend(dev_priv);
+
        cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
        cancel_delayed_work_sync(&dev_priv->gt.retire_work);
 
index 11898cd97596a33965a54c2bf459dcc7d12608dd..f225bf680b6de190ce1cbb4aa0e67a5b3d5f603a 100644 (file)
@@ -200,10 +200,10 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
        .map_dma_buf = i915_gem_map_dma_buf,
        .unmap_dma_buf = i915_gem_unmap_dma_buf,
        .release = drm_gem_dmabuf_release,
-       .kmap = i915_gem_dmabuf_kmap,
-       .kmap_atomic = i915_gem_dmabuf_kmap_atomic,
-       .kunmap = i915_gem_dmabuf_kunmap,
-       .kunmap_atomic = i915_gem_dmabuf_kunmap_atomic,
+       .map = i915_gem_dmabuf_kmap,
+       .map_atomic = i915_gem_dmabuf_kmap_atomic,
+       .unmap = i915_gem_dmabuf_kunmap,
+       .unmap_atomic = i915_gem_dmabuf_kunmap_atomic,
        .mmap = i915_gem_dmabuf_mmap,
        .vmap = i915_gem_dmabuf_vmap,
        .vunmap = i915_gem_dmabuf_vunmap,
index 2978acdd995e7580a70fb24536543d2ec7306c9c..129ed303a6c46e2f856eb1abc84990079abefb65 100644 (file)
@@ -53,6 +53,17 @@ static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
        BUG();
 }
 
+static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock)
+{
+       if (!unlock)
+               return;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       /* expedite the RCU grace period to free some request slabs */
+       synchronize_rcu_expedited();
+}
+
 static bool any_vma_pinned(struct drm_i915_gem_object *obj)
 {
        struct i915_vma *vma;
@@ -232,11 +243,8 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
                intel_runtime_pm_put(dev_priv);
 
        i915_gem_retire_requests(dev_priv);
-       if (unlock)
-               mutex_unlock(&dev_priv->drm.struct_mutex);
 
-       /* expedite the RCU grace period to free some request slabs */
-       synchronize_rcu_expedited();
+       i915_gem_shrinker_unlock(&dev_priv->drm, unlock);
 
        return count;
 }
@@ -296,8 +304,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
                        count += obj->base.size >> PAGE_SHIFT;
        }
 
-       if (unlock)
-               mutex_unlock(&dev->struct_mutex);
+       i915_gem_shrinker_unlock(dev, unlock);
 
        return count;
 }
@@ -324,8 +331,8 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
                                         sc->nr_to_scan - freed,
                                         I915_SHRINK_BOUND |
                                         I915_SHRINK_UNBOUND);
-       if (unlock)
-               mutex_unlock(&dev->struct_mutex);
+
+       i915_gem_shrinker_unlock(dev, unlock);
 
        return freed;
 }
@@ -367,8 +374,7 @@ i915_gem_shrinker_unlock_uninterruptible(struct drm_i915_private *dev_priv,
                                         struct shrinker_lock_uninterruptible *slu)
 {
        dev_priv->mm.interruptible = slu->was_interruptible;
-       if (slu->unlock)
-               mutex_unlock(&dev_priv->drm.struct_mutex);
+       i915_gem_shrinker_unlock(&dev_priv->drm, slu->unlock);
 }
 
 static int
index 99da8f4ef49712edb46c202d25cf7d957ce4e36e..302f7d1036359ab47db4009037561b99e2d617d6 100644 (file)
@@ -129,10 +129,10 @@ static const struct dma_buf_ops mock_dmabuf_ops =  {
        .map_dma_buf = mock_map_dma_buf,
        .unmap_dma_buf = mock_unmap_dma_buf,
        .release = mock_dmabuf_release,
-       .kmap = mock_dmabuf_kmap,
-       .kmap_atomic = mock_dmabuf_kmap_atomic,
-       .kunmap = mock_dmabuf_kunmap,
-       .kunmap_atomic = mock_dmabuf_kunmap_atomic,
+       .map = mock_dmabuf_kmap,
+       .map_atomic = mock_dmabuf_kmap_atomic,
+       .unmap = mock_dmabuf_kunmap,
+       .unmap_atomic = mock_dmabuf_kunmap_atomic,
        .mmap = mock_dmabuf_mmap,
        .vmap = mock_dmabuf_vmap,
        .vunmap = mock_dmabuf_vunmap,
index ee5883f59be5a1992c6bdd20c751285079f5d3c1..0dbe0306953da431978263bff9f7c96b60e31fb6 100644 (file)
@@ -160,10 +160,10 @@ static struct dma_buf_ops omap_dmabuf_ops = {
        .release = omap_gem_dmabuf_release,
        .begin_cpu_access = omap_gem_dmabuf_begin_cpu_access,
        .end_cpu_access = omap_gem_dmabuf_end_cpu_access,
-       .kmap_atomic = omap_gem_dmabuf_kmap_atomic,
-       .kunmap_atomic = omap_gem_dmabuf_kunmap_atomic,
-       .kmap = omap_gem_dmabuf_kmap,
-       .kunmap = omap_gem_dmabuf_kunmap,
+       .map_atomic = omap_gem_dmabuf_kmap_atomic,
+       .unmap_atomic = omap_gem_dmabuf_kunmap_atomic,
+       .map = omap_gem_dmabuf_kmap,
+       .unmap = omap_gem_dmabuf_kunmap,
        .mmap = omap_gem_dmabuf_mmap,
 };
 
index 86279f5022c28a6ccf00efa66fff90f21a136f21..88f16cdf6a4bcee03adc0c1145eaae317eb7d2ef 100644 (file)
@@ -66,7 +66,9 @@ static struct gdp_format_to_str {
 #define GAM_GDP_ALPHARANGE_255  BIT(5)
 #define GAM_GDP_AGC_FULL_RANGE  0x00808080
 #define GAM_GDP_PPT_IGNORE      (BIT(1) | BIT(0))
-#define GAM_GDP_SIZE_MAX        0x7FF
+
+#define GAM_GDP_SIZE_MAX_WIDTH  3840
+#define GAM_GDP_SIZE_MAX_HEIGHT 2160
 
 #define GDP_NODE_NB_BANK        2
 #define GDP_NODE_PER_FIELD      2
@@ -632,8 +634,8 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
        /* src_x are in 16.16 format */
        src_x = state->src_x >> 16;
        src_y = state->src_y >> 16;
-       src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX);
-       src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX);
+       src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX_WIDTH);
+       src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX_HEIGHT);
 
        format = sti_gdp_fourcc2format(fb->format->format);
        if (format == -1) {
@@ -741,8 +743,8 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
        /* src_x are in 16.16 format */
        src_x = state->src_x >> 16;
        src_y = state->src_y >> 16;
-       src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX);
-       src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX);
+       src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX_WIDTH);
+       src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX_HEIGHT);
 
        list = sti_gdp_get_free_nodes(gdp);
        top_field = list->top_field;
index d625a82a6e5fb8e570764e26aa2e202f5f65bc0d..59b757350a1f5516d5a9558c7cbfddf3a7192741 100644 (file)
@@ -1,11 +1,11 @@
-sun4i-drm-y += sun4i_crtc.o
 sun4i-drm-y += sun4i_drv.o
 sun4i-drm-y += sun4i_framebuffer.o
-sun4i-drm-y += sun4i_layer.o
 
 sun4i-tcon-y += sun4i_tcon.o
 sun4i-tcon-y += sun4i_rgb.o
 sun4i-tcon-y += sun4i_dotclock.o
+sun4i-tcon-y += sun4i_crtc.o
+sun4i-tcon-y += sun4i_layer.o
 
 obj-$(CONFIG_DRM_SUN4I)                += sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I)                += sun4i_backend.o
index 08ce15070f80f0c6b11a2bf1648711a647f695f0..d660741ba475af98c22d36275f950661c6b98a9e 100644 (file)
@@ -24,7 +24,7 @@
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
 
-static u32 sunxi_rgb2yuv_coef[12] = {
+static const u32 sunxi_rgb2yuv_coef[12] = {
        0x00000107, 0x00000204, 0x00000064, 0x00000108,
        0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
        0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
index a5d546a68e1651edb9e19bcdfd66da0f42cb6de8..3c876c3a356a635aeef947e99f3d9f89aad6cbea 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/clk-provider.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
+#include <linux/of_graph.h>
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
 
@@ -27,6 +28,7 @@
 #include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
+#include "sun4i_layer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -50,12 +52,11 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_state)
 {
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
-       struct sun4i_drv *drv = scrtc->drv;
        struct drm_pending_vblank_event *event = crtc->state->event;
 
        DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-       sun4i_backend_commit(drv->backend);
+       sun4i_backend_commit(scrtc->backend);
 
        if (event) {
                crtc->state->event = NULL;
@@ -72,11 +73,10 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 static void sun4i_crtc_disable(struct drm_crtc *crtc)
 {
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
-       struct sun4i_drv *drv = scrtc->drv;
 
        DRM_DEBUG_DRIVER("Disabling the CRTC\n");
 
-       sun4i_tcon_disable(drv->tcon);
+       sun4i_tcon_disable(scrtc->tcon);
 
        if (crtc->state->event && !crtc->state->active) {
                spin_lock_irq(&crtc->dev->event_lock);
@@ -90,11 +90,10 @@ static void sun4i_crtc_disable(struct drm_crtc *crtc)
 static void sun4i_crtc_enable(struct drm_crtc *crtc)
 {
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
-       struct sun4i_drv *drv = scrtc->drv;
 
        DRM_DEBUG_DRIVER("Enabling the CRTC\n");
 
-       sun4i_tcon_enable(drv->tcon);
+       sun4i_tcon_enable(scrtc->tcon);
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
@@ -107,11 +106,10 @@ static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
 static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
 {
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
-       struct sun4i_drv *drv = scrtc->drv;
 
        DRM_DEBUG_DRIVER("Enabling VBLANK on crtc %p\n", crtc);
 
-       sun4i_tcon_enable_vblank(drv->tcon, true);
+       sun4i_tcon_enable_vblank(scrtc->tcon, true);
 
        return 0;
 }
@@ -119,11 +117,10 @@ static int sun4i_crtc_enable_vblank(struct drm_crtc *crtc)
 static void sun4i_crtc_disable_vblank(struct drm_crtc *crtc)
 {
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
-       struct sun4i_drv *drv = scrtc->drv;
 
        DRM_DEBUG_DRIVER("Disabling VBLANK on crtc %p\n", crtc);
 
-       sun4i_tcon_enable_vblank(drv->tcon, false);
+       sun4i_tcon_enable_vblank(scrtc->tcon, false);
 }
 
 static const struct drm_crtc_funcs sun4i_crtc_funcs = {
@@ -137,28 +134,67 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
        .disable_vblank         = sun4i_crtc_disable_vblank,
 };
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm)
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
+                                  struct sun4i_backend *backend,
+                                  struct sun4i_tcon *tcon)
 {
-       struct sun4i_drv *drv = drm->dev_private;
        struct sun4i_crtc *scrtc;
-       int ret;
+       struct drm_plane *primary = NULL, *cursor = NULL;
+       int ret, i;
 
        scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
        if (!scrtc)
+               return ERR_PTR(-ENOMEM);
+       scrtc->backend = backend;
+       scrtc->tcon = tcon;
+
+       /* Create our layers */
+       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+       if (IS_ERR(scrtc->layers)) {
+               dev_err(drm->dev, "Couldn't create the planes\n");
                return NULL;
-       scrtc->drv = drv;
+       }
+
+       /* find primary and cursor planes for drm_crtc_init_with_planes */
+       for (i = 0; scrtc->layers[i]; i++) {
+               struct sun4i_layer *layer = scrtc->layers[i];
+
+               switch (layer->plane.type) {
+               case DRM_PLANE_TYPE_PRIMARY:
+                       primary = &layer->plane;
+                       break;
+               case DRM_PLANE_TYPE_CURSOR:
+                       cursor = &layer->plane;
+                       break;
+               default:
+                       break;
+               }
+       }
 
        ret = drm_crtc_init_with_planes(drm, &scrtc->crtc,
-                                       drv->primary,
-                                       NULL,
+                                       primary,
+                                       cursor,
                                        &sun4i_crtc_funcs,
                                        NULL);
        if (ret) {
                dev_err(drm->dev, "Couldn't init DRM CRTC\n");
-               return NULL;
+               return ERR_PTR(ret);
        }
 
        drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs);
 
+       /* Set crtc.port to output port node of the tcon */
+       scrtc->crtc.port = of_graph_get_port_by_id(scrtc->tcon->dev->of_node,
+                                                  1);
+
+       /* Set possible_crtcs to this crtc for overlay planes */
+       for (i = 0; scrtc->layers[i]; i++) {
+               uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
+               struct sun4i_layer *layer = scrtc->layers[i];
+
+               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
+                       layer->plane.possible_crtcs = possible_crtcs;
+       }
+
        return scrtc;
 }
index dec8ce4d9b25b79c7c3de4272a924d5464031e1f..230cb8f0d60166087e33dce3893bec541baf5954 100644 (file)
@@ -17,7 +17,9 @@ struct sun4i_crtc {
        struct drm_crtc                 crtc;
        struct drm_pending_vblank_event *event;
 
-       struct sun4i_drv                *drv;
+       struct sun4i_backend            *backend;
+       struct sun4i_tcon               *tcon;
+       struct sun4i_layer              **layers;
 };
 
 static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
@@ -25,6 +27,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
        return container_of(crtc, struct sun4i_crtc, crtc);
 }
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm);
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
+                                  struct sun4i_backend *backend,
+                                  struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
index 329ea56106a5c1e546d4dbd9b0f654884f0b3b6d..8ddd72cd58736e3f6e0935087cccdab802e6dd96 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/component.h>
 #include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_of.h>
 
-#include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_framebuffer.h"
-#include "sun4i_layer.h"
+#include "sun4i_tcon.h"
 
 DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
 
@@ -92,30 +92,25 @@ static int sun4i_drv_bind(struct device *dev)
        }
        drm->dev_private = drv;
 
-       drm_vblank_init(drm, 1);
+       ret = of_reserved_mem_device_init(dev);
+       if (ret && ret != -ENODEV) {
+               dev_err(drm->dev, "Couldn't claim our memory region\n");
+               goto free_drm;
+       }
+
+       /* drm_vblank_init calls kcalloc, which can fail */
+       ret = drm_vblank_init(drm, 1);
+       if (ret)
+               goto free_mem_region;
+
        drm_mode_config_init(drm);
 
        ret = component_bind_all(drm->dev, drm);
        if (ret) {
                dev_err(drm->dev, "Couldn't bind all pipelines components\n");
-               goto free_drm;
-       }
-
-       /* Create our layers */
-       drv->layers = sun4i_layers_init(drm);
-       if (IS_ERR(drv->layers)) {
-               dev_err(drm->dev, "Couldn't create the planes\n");
-               ret = PTR_ERR(drv->layers);
-               goto free_drm;
+               goto cleanup_mode_config;
        }
 
-       /* Create our CRTC */
-       drv->crtc = sun4i_crtc_init(drm);
-       if (!drv->crtc) {
-               dev_err(drm->dev, "Couldn't create the CRTC\n");
-               ret = -EINVAL;
-               goto free_drm;
-       }
        drm->irq_enabled = true;
 
        /* Remove early framebuffers (ie. simplefb) */
@@ -126,7 +121,7 @@ static int sun4i_drv_bind(struct device *dev)
        if (IS_ERR(drv->fbdev)) {
                dev_err(drm->dev, "Couldn't create our framebuffer\n");
                ret = PTR_ERR(drv->fbdev);
-               goto free_drm;
+               goto cleanup_mode_config;
        }
 
        /* Enable connectors polling */
@@ -134,10 +129,18 @@ static int sun4i_drv_bind(struct device *dev)
 
        ret = drm_dev_register(drm, 0);
        if (ret)
-               goto free_drm;
+               goto finish_poll;
 
        return 0;
 
+finish_poll:
+       drm_kms_helper_poll_fini(drm);
+       sun4i_framebuffer_free(drm);
+cleanup_mode_config:
+       drm_mode_config_cleanup(drm);
+       drm_vblank_cleanup(drm);
+free_mem_region:
+       of_reserved_mem_device_release(dev);
 free_drm:
        drm_dev_unref(drm);
        return ret;
@@ -150,7 +153,9 @@ static void sun4i_drv_unbind(struct device *dev)
        drm_dev_unregister(drm);
        drm_kms_helper_poll_fini(drm);
        sun4i_framebuffer_free(drm);
+       drm_mode_config_cleanup(drm);
        drm_vblank_cleanup(drm);
+       of_reserved_mem_device_release(dev);
        drm_dev_unref(drm);
 }
 
index 597353eab728f240566d206433b367ffe194e9f1..5df50126ff52531be776e79db00f629347efae25 100644 (file)
 
 struct sun4i_drv {
        struct sun4i_backend    *backend;
-       struct sun4i_crtc       *crtc;
        struct sun4i_tcon       *tcon;
 
-       struct drm_plane        *primary;
        struct drm_fbdev_cma    *fbdev;
-
-       struct sun4i_layer      **layers;
 };
 
 #endif /* _SUN4I_DRV_H_ */
index 2c3beff8b53e2d89de3a6d4e705ae3b9b047ae2f..9872e0fc03b0ec44db0d3ac01c5106ec5d9d426f 100644 (file)
@@ -48,5 +48,4 @@ void sun4i_framebuffer_free(struct drm_device *drm)
        struct sun4i_drv *drv = drm->dev_private;
 
        drm_fbdev_cma_fini(drv->fbdev);
-       drm_mode_config_cleanup(drm);
 }
index 5d53c977bca5d0cce752e389f7dc9b38ce195155..f26bde5b9117cabaa6d0cf08af9471cee80f45e8 100644 (file)
@@ -16,7 +16,6 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
-#include "sun4i_drv.h"
 #include "sun4i_layer.h"
 
 struct sun4i_plane_desc {
@@ -36,8 +35,7 @@ static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane,
                                               struct drm_plane_state *old_state)
 {
        struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
-       struct sun4i_drv *drv = layer->drv;
-       struct sun4i_backend *backend = drv->backend;
+       struct sun4i_backend *backend = layer->backend;
 
        sun4i_backend_layer_enable(backend, layer->id, false);
 }
@@ -46,8 +44,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
                                              struct drm_plane_state *old_state)
 {
        struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
-       struct sun4i_drv *drv = layer->drv;
-       struct sun4i_backend *backend = drv->backend;
+       struct sun4i_backend *backend = layer->backend;
 
        sun4i_backend_update_layer_coord(backend, layer->id, plane);
        sun4i_backend_update_layer_formats(backend, layer->id, plane);
@@ -104,9 +101,9 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 };
 
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
+                                               struct sun4i_backend *backend,
                                                const struct sun4i_plane_desc *plane)
 {
-       struct sun4i_drv *drv = drm->dev_private;
        struct sun4i_layer *layer;
        int ret;
 
@@ -114,7 +111,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
        if (!layer)
                return ERR_PTR(-ENOMEM);
 
-       ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
+       /* possible crtcs are set later */
+       ret = drm_universal_plane_init(drm, &layer->plane, 0,
                                       &sun4i_backend_layer_funcs,
                                       plane->formats, plane->nformats,
                                       plane->type, NULL);
@@ -125,22 +123,19 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 
        drm_plane_helper_add(&layer->plane,
                             &sun4i_backend_layer_helper_funcs);
-       layer->drv = drv;
-
-       if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-               drv->primary = &layer->plane;
+       layer->backend = backend;
 
        return layer;
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
+struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
+                                      struct sun4i_backend *backend)
 {
-       struct sun4i_drv *drv = drm->dev_private;
        struct sun4i_layer **layers;
        int i;
 
-       layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes),
-                             sizeof(**layers), GFP_KERNEL);
+       layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
+                             sizeof(*layers), GFP_KERNEL);
        if (!layers)
                return ERR_PTR(-ENOMEM);
 
@@ -167,9 +162,9 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
         */
        for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) {
                const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
-               struct sun4i_layer *layer = layers[i];
+               struct sun4i_layer *layer;
 
-               layer = sun4i_layer_init_one(drm, plane);
+               layer = sun4i_layer_init_one(drm, backend, plane);
                if (IS_ERR(layer)) {
                        dev_err(drm->dev, "Couldn't initialize %s plane\n",
                                i ? "overlay" : "primary");
@@ -178,11 +173,12 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
 
                DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
                                 i ? "overlay" : "primary", plane->pipe);
-               regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
+               regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
                                   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
                                   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
 
                layer->id = i;
+               layers[i] = layer;
        };
 
        return layers;
index a2f65d7a3f4e930dd5020dd8297f6780406ab9be..4be1f0919df22cd5b6478f2f2f24ef1324ba3048 100644 (file)
@@ -16,6 +16,7 @@
 struct sun4i_layer {
        struct drm_plane        plane;
        struct sun4i_drv        *drv;
+       struct sun4i_backend    *backend;
        int                     id;
 };
 
@@ -25,6 +26,7 @@ plane_to_sun4i_layer(struct drm_plane *plane)
        return container_of(plane, struct sun4i_layer, plane);
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm);
+struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
+                                      struct sun4i_backend *backend);
 
 #endif /* _SUN4I_LAYER_H_ */
index 46280dd70c9e05800aed87a6de4e512066da46e9..67f0b91a99de057933583d8aa786f23c73cb1af8 100644 (file)
@@ -18,7 +18,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
-#include "sun4i_drv.h"
+#include "sun4i_crtc.h"
 #include "sun4i_tcon.h"
 #include "sun4i_rgb.h"
 
@@ -26,7 +26,7 @@ struct sun4i_rgb {
        struct drm_connector    connector;
        struct drm_encoder      encoder;
 
-       struct sun4i_drv        *drv;
+       struct sun4i_tcon       *tcon;
 };
 
 static inline struct sun4i_rgb *
@@ -47,8 +47,7 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector)
 {
        struct sun4i_rgb *rgb =
                drm_connector_to_sun4i_rgb(connector);
-       struct sun4i_drv *drv = rgb->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_tcon *tcon = rgb->tcon;
 
        return drm_panel_get_modes(tcon->panel);
 }
@@ -57,8 +56,7 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
        struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
-       struct sun4i_drv *drv = rgb->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_tcon *tcon = rgb->tcon;
        u32 hsync = mode->hsync_end - mode->hsync_start;
        u32 vsync = mode->vsync_end - mode->vsync_start;
        unsigned long rate = mode->clock * 1000;
@@ -115,8 +113,7 @@ static void
 sun4i_rgb_connector_destroy(struct drm_connector *connector)
 {
        struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
-       struct sun4i_drv *drv = rgb->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_tcon *tcon = rgb->tcon;
 
        drm_panel_detach(tcon->panel);
        drm_connector_cleanup(connector);
@@ -141,8 +138,7 @@ static int sun4i_rgb_atomic_check(struct drm_encoder *encoder,
 static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 {
        struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-       struct sun4i_drv *drv = rgb->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_tcon *tcon = rgb->tcon;
 
        DRM_DEBUG_DRIVER("Enabling RGB output\n");
 
@@ -158,8 +154,7 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 {
        struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-       struct sun4i_drv *drv = rgb->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_tcon *tcon = rgb->tcon;
 
        DRM_DEBUG_DRIVER("Disabling RGB output\n");
 
@@ -177,8 +172,7 @@ static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
                                       struct drm_display_mode *adjusted_mode)
 {
        struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
-       struct sun4i_drv *drv = rgb->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_tcon *tcon = rgb->tcon;
 
        sun4i_tcon0_mode_set(tcon, mode);
 
@@ -204,10 +198,8 @@ static struct drm_encoder_funcs sun4i_rgb_enc_funcs = {
        .destroy        = sun4i_rgb_enc_destroy,
 };
 
-int sun4i_rgb_init(struct drm_device *drm)
+int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon)
 {
-       struct sun4i_drv *drv = drm->dev_private;
-       struct sun4i_tcon *tcon = drv->tcon;
        struct drm_encoder *encoder;
        struct drm_bridge *bridge;
        struct sun4i_rgb *rgb;
@@ -216,7 +208,7 @@ int sun4i_rgb_init(struct drm_device *drm)
        rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
        if (!rgb)
                return -ENOMEM;
-       rgb->drv = drv;
+       rgb->tcon = tcon;
        encoder = &rgb->encoder;
 
        ret = drm_of_find_panel_or_bridge(tcon->dev->of_node, 1, 0,
@@ -239,7 +231,7 @@ int sun4i_rgb_init(struct drm_device *drm)
        }
 
        /* The RGB encoder can only work with the TCON channel 0 */
-       rgb->encoder.possible_crtcs = BIT(0);
+       rgb->encoder.possible_crtcs = BIT(drm_crtc_index(&tcon->crtc->crtc));
 
        if (tcon->panel) {
                drm_connector_helper_add(&rgb->connector,
index 7c4da4c8acdd452f8d24ad4ba0e863001ebf3e44..40c18f4a6c7e960af334ae897d76c9819fc8b934 100644 (file)
@@ -13,6 +13,6 @@
 #ifndef _SUN4I_RGB_H_
 #define _SUN4I_RGB_H_
 
-int sun4i_rgb_init(struct drm_device *drm);
+int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_RGB_H_ */
index 2e4e365cecf9f506823fae7fe3bcb4c94863b3ea..9a83a85529ac46ab0b351e7111cded6ef7313259 100644 (file)
@@ -142,7 +142,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 
        /*
         * This is called a backporch in the register documentation,
-        * but it really is the front porch + hsync
+        * but it really is the back porch + hsync
         */
        bp = mode->crtc_htotal - mode->crtc_hsync_start;
        DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
@@ -155,7 +155,7 @@ void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
 
        /*
         * This is called a backporch in the register documentation,
-        * but it really is the front porch + hsync
+        * but it really is the back porch + hsync
         */
        bp = mode->crtc_vtotal - mode->crtc_vsync_start;
        DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
@@ -289,8 +289,7 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private)
 {
        struct sun4i_tcon *tcon = private;
        struct drm_device *drm = tcon->drm;
-       struct sun4i_drv *drv = drm->dev_private;
-       struct sun4i_crtc *scrtc = drv->crtc;
+       struct sun4i_crtc *scrtc = tcon->crtc;
        unsigned int status;
 
        regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
@@ -335,12 +334,11 @@ static int sun4i_tcon_init_clocks(struct device *dev,
                }
        }
 
-       return sun4i_dclk_create(dev, tcon);
+       return 0;
 }
 
 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
 {
-       sun4i_dclk_free(tcon);
        clk_disable_unprepare(tcon->clk);
 }
 
@@ -437,30 +435,45 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
                return ret;
        }
 
+       ret = sun4i_tcon_init_clocks(dev, tcon);
+       if (ret) {
+               dev_err(dev, "Couldn't init our TCON clocks\n");
+               goto err_assert_reset;
+       }
+
        ret = sun4i_tcon_init_regmap(dev, tcon);
        if (ret) {
                dev_err(dev, "Couldn't init our TCON regmap\n");
-               goto err_assert_reset;
+               goto err_free_clocks;
        }
 
-       ret = sun4i_tcon_init_clocks(dev, tcon);
+       ret = sun4i_dclk_create(dev, tcon);
        if (ret) {
-               dev_err(dev, "Couldn't init our TCON clocks\n");
-               goto err_assert_reset;
+               dev_err(dev, "Couldn't create our TCON dot clock\n");
+               goto err_free_clocks;
        }
 
        ret = sun4i_tcon_init_irq(dev, tcon);
        if (ret) {
                dev_err(dev, "Couldn't init our TCON interrupts\n");
+               goto err_free_dotclock;
+       }
+
+       tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+       if (IS_ERR(tcon->crtc)) {
+               dev_err(dev, "Couldn't create our CRTC\n");
+               ret = PTR_ERR(tcon->crtc);
                goto err_free_clocks;
        }
 
-       ret = sun4i_rgb_init(drm);
+       ret = sun4i_rgb_init(drm, tcon);
        if (ret < 0)
                goto err_free_clocks;
 
        return 0;
 
+err_free_dotclock:
+       sun4i_dclk_free(tcon);
 err_free_clocks:
        sun4i_tcon_free_clocks(tcon);
 err_assert_reset:
@@ -473,6 +486,7 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
 {
        struct sun4i_tcon *tcon = dev_get_drvdata(dev);
 
+       sun4i_dclk_free(tcon);
        sun4i_tcon_free_clocks(tcon);
 }
 
index 166064bafe2eb3b914ed52ea1cbf200501885846..f636343a935dce6889d9f0651354191b9af03c6d 100644 (file)
@@ -169,6 +169,9 @@ struct sun4i_tcon {
 
        /* Platform adjustments */
        const struct sun4i_tcon_quirks  *quirks;
+
+       /* Associated crtc */
+       struct sun4i_crtc               *crtc;
 };
 
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
index c6f47222e8fc733fb73e0a944b545cb0f7e266a8..49c49431a053e34a3ebb9cb34a7490adda1c2860 100644 (file)
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
 #include "sun4i_backend.h"
+#include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_tcon.h"
 
@@ -349,8 +351,9 @@ static int sun4i_tv_atomic_check(struct drm_encoder *encoder,
 static void sun4i_tv_disable(struct drm_encoder *encoder)
 {
        struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-       struct sun4i_drv *drv = tv->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+       struct sun4i_tcon *tcon = crtc->tcon;
+       struct sun4i_backend *backend = crtc->backend;
 
        DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
@@ -359,18 +362,19 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
        regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
                           SUN4I_TVE_EN_ENABLE,
                           0);
-       sun4i_backend_disable_color_correction(drv->backend);
+       sun4i_backend_disable_color_correction(backend);
 }
 
 static void sun4i_tv_enable(struct drm_encoder *encoder)
 {
        struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-       struct sun4i_drv *drv = tv->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+       struct sun4i_tcon *tcon = crtc->tcon;
+       struct sun4i_backend *backend = crtc->backend;
 
        DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
-       sun4i_backend_apply_color_correction(drv->backend);
+       sun4i_backend_apply_color_correction(backend);
 
        regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
                           SUN4I_TVE_EN_ENABLE,
@@ -384,8 +388,8 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder,
                              struct drm_display_mode *adjusted_mode)
 {
        struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
-       struct sun4i_drv *drv = tv->drv;
-       struct sun4i_tcon *tcon = drv->tcon;
+       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+       struct sun4i_tcon *tcon = crtc->tcon;
        const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
 
        sun4i_tcon1_mode_set(tcon, mode);
@@ -623,7 +627,12 @@ static int sun4i_tv_bind(struct device *dev, struct device *master,
                goto err_disable_clk;
        }
 
-       tv->encoder.possible_crtcs = BIT(0);
+       tv->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm,
+                                                               dev->of_node);
+       if (!tv->encoder.possible_crtcs) {
+               ret = -EPROBE_DEFER;
+               goto err_disable_clk;
+       }
 
        drm_connector_helper_add(&tv->connector,
                                 &sun4i_tv_comp_connector_helper_funcs);
index 17e62ecb5d4d59d009ef019adb07b0335f60a87d..8672f5d2f2376d71701359268117003612552d72 100644 (file)
@@ -619,10 +619,10 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = {
        .map_dma_buf = tegra_gem_prime_map_dma_buf,
        .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf,
        .release = tegra_gem_prime_release,
-       .kmap_atomic = tegra_gem_prime_kmap_atomic,
-       .kunmap_atomic = tegra_gem_prime_kunmap_atomic,
-       .kmap = tegra_gem_prime_kmap,
-       .kunmap = tegra_gem_prime_kunmap,
+       .map_atomic = tegra_gem_prime_kmap_atomic,
+       .unmap_atomic = tegra_gem_prime_kunmap_atomic,
+       .map = tegra_gem_prime_kmap,
+       .unmap = tegra_gem_prime_kunmap,
        .mmap = tegra_gem_prime_mmap,
        .vmap = tegra_gem_prime_vmap,
        .vunmap = tegra_gem_prime_vunmap,
index ac90ffdb59120f3505a99565250655c7c8876436..ed0e636243b20c646352d01a75204c107908a219 100644 (file)
@@ -191,10 +191,10 @@ static struct dma_buf_ops udl_dmabuf_ops = {
        .detach                 = udl_detach_dma_buf,
        .map_dma_buf            = udl_map_dma_buf,
        .unmap_dma_buf          = udl_unmap_dma_buf,
-       .kmap                   = udl_dmabuf_kmap,
-       .kmap_atomic            = udl_dmabuf_kmap_atomic,
-       .kunmap                 = udl_dmabuf_kunmap,
-       .kunmap_atomic          = udl_dmabuf_kunmap_atomic,
+       .map                    = udl_dmabuf_kmap,
+       .map_atomic             = udl_dmabuf_kmap_atomic,
+       .unmap                  = udl_dmabuf_kunmap,
+       .unmap_atomic           = udl_dmabuf_kunmap_atomic,
        .mmap                   = udl_dmabuf_mmap,
        .release                = drm_gem_dmabuf_release,
 };
index 917dcb978c2ccc921c1dfcf90329973ff3044b59..0c87b1ac6b68f0d41cfd01851a14b9a092455f4f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/prefetch.h>
+#include <asm/unaligned.h>
 
 #include <drm/drmP.h>
 #include "udl_drv.h"
@@ -163,7 +164,7 @@ static void udl_compress_hline16(
                        const u8 *const start = pixel;
                        const uint16_t repeating_pixel_val16 = pixel_val16;
 
-                       *(uint16_t *)cmd = cpu_to_be16(pixel_val16);
+                       put_unaligned_be16(pixel_val16, cmd);
 
                        cmd += 2;
                        pixel += bpp;
index f6e936d90517508e66f375734e6e2c172f9338b5..4a641555b960b8fc654c6ab89c428e783a61aad4 100644 (file)
@@ -254,7 +254,7 @@ module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
 MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
 module_param_named(force_coherent, vmw_force_coherent, int, 0600);
 MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
-module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, S_IRUSR | S_IWUSR);
+module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
 MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
 module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
 
index 31fe32d8d65aa350a207daf75865f9c806c1a322..0d42a46521fc1cc5c8083722fe03239d64ae3d87 100644 (file)
@@ -108,10 +108,10 @@ const struct dma_buf_ops vmw_prime_dmabuf_ops =  {
        .map_dma_buf = vmw_prime_map_dma_buf,
        .unmap_dma_buf = vmw_prime_unmap_dma_buf,
        .release = NULL,
-       .kmap = vmw_prime_dmabuf_kmap,
-       .kmap_atomic = vmw_prime_dmabuf_kmap_atomic,
-       .kunmap = vmw_prime_dmabuf_kunmap,
-       .kunmap_atomic = vmw_prime_dmabuf_kunmap_atomic,
+       .map = vmw_prime_dmabuf_kmap,
+       .map_atomic = vmw_prime_dmabuf_kmap_atomic,
+       .unmap = vmw_prime_dmabuf_kunmap,
+       .unmap_atomic = vmw_prime_dmabuf_kunmap_atomic,
        .mmap = vmw_prime_dmabuf_mmap,
        .vmap = vmw_prime_dmabuf_vmap,
        .vunmap = vmw_prime_dmabuf_vunmap,
index 63ec1993eaaa905af1583f7169e6be812cf0486d..d162f0dc76e3f44e2134eafa5509137ddf0cc411 100644 (file)
@@ -819,8 +819,7 @@ static int hid_scan_report(struct hid_device *hid)
                hid->group = HID_GROUP_WACOM;
                break;
        case USB_VENDOR_ID_SYNAPTICS:
-               if (hid->group == HID_GROUP_GENERIC ||
-                   hid->group == HID_GROUP_MULTITOUCH_WIN_8)
+               if (hid->group == HID_GROUP_GENERIC)
                        if ((parser->scan_flags & HID_SCAN_FLAG_VENDOR_SPECIFIC)
                            && (parser->scan_flags & HID_SCAN_FLAG_GD_POINTER))
                                /*
@@ -2096,6 +2095,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
index 4e2648c86c8c56142cd06b6a269433f72c5c07c9..b26c030926c188aff2dd054cd2ae9e9910837887 100644 (file)
 #define USB_DEVICE_ID_UGEE_TABLET_45           0x0045
 #define USB_DEVICE_ID_YIYNOVA_TABLET           0x004d
 
+#define USB_VENDOR_ID_UGEE             0x28bd
+#define USB_DEVICE_ID_UGEE_TABLET_EX07S                0x0071
+
 #define USB_VENDOR_ID_UNITEC   0x227d
 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709    0x0709
 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19    0x0a19
index 1509d7287ff3e60e79c845214e47e901fae650f8..e3e6e5c893cc05e0c934c8c9f505de9fdd06e26a 100644 (file)
@@ -977,6 +977,7 @@ static int uclogic_probe(struct hid_device *hdev,
                }
                break;
        case USB_DEVICE_ID_UGTIZER_TABLET_GP0610:
+       case USB_DEVICE_ID_UGEE_TABLET_EX07S:
                /* If this is the pen interface */
                if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
                        rc = uclogic_tablet_enable(hdev);
@@ -1069,6 +1070,7 @@ static const struct hid_device_id uclogic_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, uclogic_devices);
index 91cbe86b25c8ec2d693bea5452c04d0ffa73ba0b..fcbed35e95a824979bb48fba9f05614591e97491 100644 (file)
@@ -817,6 +817,7 @@ isert_post_recvm(struct isert_conn *isert_conn, u32 count)
                rx_wr->sg_list = &rx_desc->rx_sg;
                rx_wr->num_sge = 1;
                rx_wr->next = rx_wr + 1;
+               rx_desc->in_use = false;
        }
        rx_wr--;
        rx_wr->next = NULL; /* mark end of work requests list */
@@ -835,6 +836,15 @@ isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc)
        struct ib_recv_wr *rx_wr_failed, rx_wr;
        int ret;
 
+       if (!rx_desc->in_use) {
+               /*
+                * if the descriptor is not in-use we already reposted it
+                * for recv, so just silently return
+                */
+               return 0;
+       }
+
+       rx_desc->in_use = false;
        rx_wr.wr_cqe = &rx_desc->rx_cqe;
        rx_wr.sg_list = &rx_desc->rx_sg;
        rx_wr.num_sge = 1;
@@ -1397,6 +1407,8 @@ isert_recv_done(struct ib_cq *cq, struct ib_wc *wc)
                return;
        }
 
+       rx_desc->in_use = true;
+
        ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
                        ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
 
@@ -1659,10 +1671,23 @@ isert_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
        ret = isert_check_pi_status(cmd, isert_cmd->rw.sig->sig_mr);
        isert_rdma_rw_ctx_destroy(isert_cmd, isert_conn);
 
-       if (ret)
-               transport_send_check_condition_and_sense(cmd, cmd->pi_err, 0);
-       else
-               isert_put_response(isert_conn->conn, isert_cmd->iscsi_cmd);
+       if (ret) {
+               /*
+                * transport_generic_request_failure() expects to have
+                * plus two references to handle queue-full, so re-add
+                * one here as target-core will have already dropped
+                * it after the first isert_put_datain() callback.
+                */
+               kref_get(&cmd->cmd_kref);
+               transport_generic_request_failure(cmd, cmd->pi_err);
+       } else {
+               /*
+                * XXX: isert_put_response() failure is not retried.
+                */
+               ret = isert_put_response(isert_conn->conn, isert_cmd->iscsi_cmd);
+               if (ret)
+                       pr_warn_ratelimited("isert_put_response() ret: %d\n", ret);
+       }
 }
 
 static void
@@ -1699,13 +1724,15 @@ isert_rdma_read_done(struct ib_cq *cq, struct ib_wc *wc)
        cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
        spin_unlock_bh(&cmd->istate_lock);
 
-       if (ret) {
-               target_put_sess_cmd(se_cmd);
-               transport_send_check_condition_and_sense(se_cmd,
-                                                        se_cmd->pi_err, 0);
-       } else {
+       /*
+        * transport_generic_request_failure() will drop the extra
+        * se_cmd->cmd_kref reference after T10-PI error, and handle
+        * any non-zero ->queue_status() callback error retries.
+        */
+       if (ret)
+               transport_generic_request_failure(se_cmd, se_cmd->pi_err);
+       else
                target_execute_cmd(se_cmd);
-       }
 }
 
 static void
@@ -2171,26 +2198,28 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                chain_wr = &isert_cmd->tx_desc.send_wr;
        }
 
-       isert_rdma_rw_ctx_post(isert_cmd, isert_conn, cqe, chain_wr);
-       isert_dbg("Cmd: %p posted RDMA_WRITE for iSER Data READ\n", isert_cmd);
-       return 1;
+       rc = isert_rdma_rw_ctx_post(isert_cmd, isert_conn, cqe, chain_wr);
+       isert_dbg("Cmd: %p posted RDMA_WRITE for iSER Data READ rc: %d\n",
+                 isert_cmd, rc);
+       return rc;
 }
 
 static int
 isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
+       int ret;
 
        isert_dbg("Cmd: %p RDMA_READ data_length: %u write_data_done: %u\n",
                 isert_cmd, cmd->se_cmd.data_length, cmd->write_data_done);
 
        isert_cmd->tx_desc.tx_cqe.done = isert_rdma_read_done;
-       isert_rdma_rw_ctx_post(isert_cmd, conn->context,
-                       &isert_cmd->tx_desc.tx_cqe, NULL);
+       ret = isert_rdma_rw_ctx_post(isert_cmd, conn->context,
+                                    &isert_cmd->tx_desc.tx_cqe, NULL);
 
-       isert_dbg("Cmd: %p posted RDMA_READ memory for ISER Data WRITE\n",
-                isert_cmd);
-       return 0;
+       isert_dbg("Cmd: %p posted RDMA_READ memory for ISER Data WRITE rc: %d\n",
+                isert_cmd, ret);
+       return ret;
 }
 
 static int
index c02ada57d7f5c4fa5b765a6401ac8e7bbd6096bb..87d994de8c910d998c12a4205c0e66eb1220b12d 100644 (file)
@@ -60,7 +60,7 @@
 
 #define ISER_RX_PAD_SIZE       (ISCSI_DEF_MAX_RECV_SEG_LEN + 4096 - \
                (ISER_RX_PAYLOAD_SIZE + sizeof(u64) + sizeof(struct ib_sge) + \
-                sizeof(struct ib_cqe)))
+                sizeof(struct ib_cqe) + sizeof(bool)))
 
 #define ISCSI_ISER_SG_TABLESIZE                256
 
@@ -85,6 +85,7 @@ struct iser_rx_desc {
        u64             dma_addr;
        struct ib_sge   rx_sg;
        struct ib_cqe   rx_cqe;
+       bool            in_use;
        char            pad[ISER_RX_PAD_SIZE];
 } __packed;
 
index 155fcb3b6230a01da6d1de3ab772e508b56fef78..153b1ee13e03eccd764d4a92a85bd579c0f89946 100644 (file)
@@ -202,6 +202,7 @@ static const struct xpad_device {
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
        { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+       { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
        { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 },
        { 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
        { 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 },
@@ -326,6 +327,7 @@ static struct usb_device_id xpad_table[] = {
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x146b),            /* BigBen Interactive Controllers */
        XPAD_XBOX360_VENDOR(0x1532),            /* Razer Sabertooth */
+       XPAD_XBOXONE_VENDOR(0x1532),            /* Razer Wildcat */
        XPAD_XBOX360_VENDOR(0x15e4),            /* Numark X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x162e),            /* Joytech X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x1689),            /* Razer Onza */
index 15af9a9753e582b797a58de3c9713226800999f8..2d203b422129e53554d5be023595c6946877037c 100644 (file)
@@ -230,6 +230,8 @@ static int __init imx_gpcv2_irqchip_init(struct device_node *node,
                return -ENOMEM;
        }
 
+       raw_spin_lock_init(&cd->rlock);
+
        cd->gpc_base = of_iomap(node, 0);
        if (!cd->gpc_base) {
                pr_err("fsl-gpcv2: unable to map gpc registers\n");
index fb6a177be46191012c7b88a09b5ab8446efed18b..2db0413f5d5744b6634f827ee169f8d95287c566 100644 (file)
@@ -356,8 +356,8 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
        .detach = vb2_dc_dmabuf_ops_detach,
        .map_dma_buf = vb2_dc_dmabuf_ops_map,
        .unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
-       .kmap = vb2_dc_dmabuf_ops_kmap,
-       .kmap_atomic = vb2_dc_dmabuf_ops_kmap,
+       .map = vb2_dc_dmabuf_ops_kmap,
+       .map_atomic = vb2_dc_dmabuf_ops_kmap,
        .vmap = vb2_dc_dmabuf_ops_vmap,
        .mmap = vb2_dc_dmabuf_ops_mmap,
        .release = vb2_dc_dmabuf_ops_release,
index ecff8f492c4ff8cdfdaf14bb5b907e8aa1ad5f9e..6fd1343b7c1367103db36fa5f00204cd48450882 100644 (file)
@@ -504,8 +504,8 @@ static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
        .detach = vb2_dma_sg_dmabuf_ops_detach,
        .map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
        .unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
-       .kmap = vb2_dma_sg_dmabuf_ops_kmap,
-       .kmap_atomic = vb2_dma_sg_dmabuf_ops_kmap,
+       .map = vb2_dma_sg_dmabuf_ops_kmap,
+       .map_atomic = vb2_dma_sg_dmabuf_ops_kmap,
        .vmap = vb2_dma_sg_dmabuf_ops_vmap,
        .mmap = vb2_dma_sg_dmabuf_ops_mmap,
        .release = vb2_dma_sg_dmabuf_ops_release,
index 3f778147cdef3e70767cc009ee1ddaee57935a08..27d1db3bb8cffafca74a0bec98b0381359378a67 100644 (file)
@@ -342,8 +342,8 @@ static struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
        .detach = vb2_vmalloc_dmabuf_ops_detach,
        .map_dma_buf = vb2_vmalloc_dmabuf_ops_map,
        .unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap,
-       .kmap = vb2_vmalloc_dmabuf_ops_kmap,
-       .kmap_atomic = vb2_vmalloc_dmabuf_ops_kmap,
+       .map = vb2_vmalloc_dmabuf_ops_kmap,
+       .map_atomic = vb2_vmalloc_dmabuf_ops_kmap,
        .vmap = vb2_vmalloc_dmabuf_ops_vmap,
        .mmap = vb2_vmalloc_dmabuf_ops_mmap,
        .release = vb2_vmalloc_dmabuf_ops_release,
index 138f5ae75c0bc6fcf912d30975197caedb0e0b3e..4d1fe8d9504234f436a0b9dd739b41089f563225 100644 (file)
@@ -557,7 +557,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
        int work_done = 0;
 
        u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
-       u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD);
+       u32 rxstcmd = readl(priv->base + IFI_CANFD_RXSTCMD);
        u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR);
 
        /* Handle bus state changes */
index caed4e6960f8c77fdca254f5ed4e7ccbe69792fc..11662f479e760ba77f613c90bfc8026b005da3ea 100644 (file)
@@ -826,8 +826,7 @@ static int rcar_can_probe(struct platform_device *pdev)
 
        devm_can_led_init(ndev);
 
-       dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n",
-                priv->regs, ndev->irq);
+       dev_info(&pdev->dev, "device registered (IRQ%d)\n", ndev->irq);
 
        return 0;
 fail_candev:
index 1b52520715aec6f972626361a6aa93accf809301..f8c81f12d988907d42786eedb6cd9e6ca3ca0015 100644 (file)
@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team,
 #define TEAM_ENC_FEATURES      (NETIF_F_HW_CSUM | NETIF_F_SG | \
                                 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
 
-static void ___team_compute_features(struct team *team)
+static void __team_compute_features(struct team *team)
 {
        struct team_port *port;
        u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
@@ -1023,16 +1023,10 @@ static void ___team_compute_features(struct team *team)
                team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
 }
 
-static void __team_compute_features(struct team *team)
-{
-       ___team_compute_features(team);
-       netdev_change_features(team->dev);
-}
-
 static void team_compute_features(struct team *team)
 {
        mutex_lock(&team->lock);
-       ___team_compute_features(team);
+       __team_compute_features(team);
        mutex_unlock(&team->lock);
        netdev_change_features(team->dev);
 }
@@ -1641,6 +1635,7 @@ static void team_uninit(struct net_device *dev)
        team_notify_peers_fini(team);
        team_queue_override_fini(team);
        mutex_unlock(&team->lock);
+       netdev_change_features(dev);
 }
 
 static void team_destructor(struct net_device *dev)
@@ -1928,6 +1923,10 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev)
        mutex_lock(&team->lock);
        err = team_port_add(team, port_dev);
        mutex_unlock(&team->lock);
+
+       if (!err)
+               netdev_change_features(dev);
+
        return err;
 }
 
@@ -1939,6 +1938,10 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
        mutex_lock(&team->lock);
        err = team_port_del(team, port_dev);
        mutex_unlock(&team->lock);
+
+       if (!err)
+               netdev_change_features(dev);
+
        return err;
 }
 
index 156f7f85e4860d682d679df68bfe8cfe2a3d4b3b..2474618404f5e592c0fe56d38c30c8988e1ed8ef 100644 (file)
@@ -908,7 +908,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2357, 0x9000, 4)},    /* TP-LINK MA260 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
-       {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)},    /* Telit LE920 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */
        {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},    /* XS Stick W100-2 from 4G Systems */
        {QMI_FIXED_INTF(0x0b3c, 0xc000, 4)},    /* Olivetti Olicard 100 */
        {QMI_FIXED_INTF(0x0b3c, 0xc001, 4)},    /* Olivetti Olicard 120 */
index 3de65ea6531a8add927c0a2d7c74e8923c0f3274..453244805c52e570394673d7a3ebd71cc62fd5ca 100644 (file)
@@ -1929,7 +1929,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
                   " value=0x%04x index=0x%04x size=%d\n",
                   cmd, reqtype, value, index, size);
 
-       if (data) {
+       if (size) {
                buf = kmalloc(size, GFP_KERNEL);
                if (!buf)
                        goto out;
@@ -1938,8 +1938,13 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
        err = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
                              cmd, reqtype, value, index, buf, size,
                              USB_CTRL_GET_TIMEOUT);
-       if (err > 0 && err <= size)
-               memcpy(data, buf, err);
+       if (err > 0 && err <= size) {
+        if (data)
+            memcpy(data, buf, err);
+        else
+            netdev_dbg(dev->net,
+                "Huh? Data requested but thrown away.\n");
+    }
        kfree(buf);
 out:
        return err;
@@ -1960,7 +1965,13 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
                buf = kmemdup(data, size, GFP_KERNEL);
                if (!buf)
                        goto out;
-       }
+       } else {
+        if (size) {
+            WARN_ON_ONCE(1);
+            err = -EINVAL;
+            goto out;
+        }
+    }
 
        err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
                              cmd, reqtype, value, index, buf, size,
index ea9890d619670e1abfba75fe608c2925d824cb1c..f36584616e7d6825c7e69137b4a31a3d55779688 100644 (file)
@@ -2230,14 +2230,8 @@ static bool virtnet_validate_features(struct virtio_device *vdev)
 #define MIN_MTU ETH_MIN_MTU
 #define MAX_MTU ETH_MAX_MTU
 
-static int virtnet_probe(struct virtio_device *vdev)
+static int virtnet_validate(struct virtio_device *vdev)
 {
-       int i, err;
-       struct net_device *dev;
-       struct virtnet_info *vi;
-       u16 max_queue_pairs;
-       int mtu;
-
        if (!vdev->config->get) {
                dev_err(&vdev->dev, "%s failure: config access disabled\n",
                        __func__);
@@ -2247,6 +2241,25 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (!virtnet_validate_features(vdev))
                return -EINVAL;
 
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_MTU)) {
+               int mtu = virtio_cread16(vdev,
+                                        offsetof(struct virtio_net_config,
+                                                 mtu));
+               if (mtu < MIN_MTU)
+                       __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
+       }
+
+       return 0;
+}
+
+static int virtnet_probe(struct virtio_device *vdev)
+{
+       int i, err;
+       struct net_device *dev;
+       struct virtnet_info *vi;
+       u16 max_queue_pairs;
+       int mtu;
+
        /* Find if host supports multiqueue virtio_net device */
        err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ,
                                   struct virtio_net_config,
@@ -2362,11 +2375,20 @@ static int virtnet_probe(struct virtio_device *vdev)
                                     offsetof(struct virtio_net_config,
                                              mtu));
                if (mtu < dev->min_mtu) {
-                       __virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
-               } else {
-                       dev->mtu = mtu;
-                       dev->max_mtu = mtu;
+                       /* Should never trigger: MTU was previously validated
+                        * in virtnet_validate.
+                        */
+                       dev_err(&vdev->dev, "device MTU appears to have changed "
+                               "it is now %d < %d", mtu, dev->min_mtu);
+                       goto free_stats;
                }
+
+               dev->mtu = mtu;
+               dev->max_mtu = mtu;
+
+               /* TODO: size buffers correctly in this case. */
+               if (dev->mtu > ETH_DATA_LEN)
+                       vi->big_packets = true;
        }
 
        if (vi->any_header_sg)
@@ -2544,6 +2566,7 @@ static struct virtio_driver virtio_net_driver = {
        .driver.name =  KBUILD_MODNAME,
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
+       .validate =     virtnet_validate,
        .probe =        virtnet_probe,
        .remove =       virtnet_remove,
        .config_changed = virtnet_config_changed,
index 23d4a1728cdfa4993903b6b4504c6a70f5a7fff4..351bac8f65031edf831741159c01e860c89bb4a5 100644 (file)
@@ -934,8 +934,14 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
        rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, NULL);
        if (rc < 0)
                goto out_unlock;
+       nvdimm_bus_unlock(&nvdimm_bus->dev);
+
        if (copy_to_user(p, buf, buf_len))
                rc = -EFAULT;
+
+       vfree(buf);
+       return rc;
+
  out_unlock:
        nvdimm_bus_unlock(&nvdimm_bus->dev);
  out:
index b3323c0697f6239ebbfe757137cde8352fe3c480..ca6d572c48fcb62d7c8a83e4874f18b625caaeb8 100644 (file)
@@ -243,7 +243,15 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns,
        }
 
        if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) {
-               if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)) {
+               /*
+                * FIXME: nsio_rw_bytes() may be called from atomic
+                * context in the btt case and nvdimm_clear_poison()
+                * takes a sleeping lock. Until the locking can be
+                * reworked this capability requires that the namespace
+                * is not claimed by btt.
+                */
+               if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)
+                               && (!ndns->claim || !is_nd_btt(ndns->claim))) {
                        long cleared;
 
                        cleared = nvdimm_clear_poison(&ndns->dev, offset, size);
index 0eedc49e0d473ed36b5ef9832760aa8498b9f146..8b721321be5b1cb291e780ae9a5ed7ea5ad67e09 100644 (file)
@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(nvdimm_create);
 
 int alias_dpa_busy(struct device *dev, void *data)
 {
-       resource_size_t map_end, blk_start, new, busy;
+       resource_size_t map_end, blk_start, new;
        struct blk_alloc_info *info = data;
        struct nd_mapping *nd_mapping;
        struct nd_region *nd_region;
@@ -436,29 +436,19 @@ int alias_dpa_busy(struct device *dev, void *data)
  retry:
        /*
         * Find the free dpa from the end of the last pmem allocation to
-        * the end of the interleave-set mapping that is not already
-        * covered by a blk allocation.
+        * the end of the interleave-set mapping.
         */
-       busy = 0;
        for_each_dpa_resource(ndd, res) {
+               if (strncmp(res->name, "pmem", 4) != 0)
+                       continue;
                if ((res->start >= blk_start && res->start < map_end)
                                || (res->end >= blk_start
                                        && res->end <= map_end)) {
-                       if (strncmp(res->name, "pmem", 4) == 0) {
-                               new = max(blk_start, min(map_end + 1,
-                                                       res->end + 1));
-                               if (new != blk_start) {
-                                       blk_start = new;
-                                       goto retry;
-                               }
-                       } else
-                               busy += min(map_end, res->end)
-                                       - max(nd_mapping->start, res->start) + 1;
-               } else if (nd_mapping->start > res->start
-                               && map_end < res->end) {
-                       /* total eclipse of the PMEM region mapping */
-                       busy += nd_mapping->size;
-                       break;
+                       new = max(blk_start, min(map_end + 1, res->end + 1));
+                       if (new != blk_start) {
+                               blk_start = new;
+                               goto retry;
+                       }
                }
        }
 
@@ -470,52 +460,11 @@ int alias_dpa_busy(struct device *dev, void *data)
                return 1;
        }
 
-       info->available -= blk_start - nd_mapping->start + busy;
+       info->available -= blk_start - nd_mapping->start;
 
        return 0;
 }
 
-static int blk_dpa_busy(struct device *dev, void *data)
-{
-       struct blk_alloc_info *info = data;
-       struct nd_mapping *nd_mapping;
-       struct nd_region *nd_region;
-       resource_size_t map_end;
-       int i;
-
-       if (!is_nd_pmem(dev))
-               return 0;
-
-       nd_region = to_nd_region(dev);
-       for (i = 0; i < nd_region->ndr_mappings; i++) {
-               nd_mapping  = &nd_region->mapping[i];
-               if (nd_mapping->nvdimm == info->nd_mapping->nvdimm)
-                       break;
-       }
-
-       if (i >= nd_region->ndr_mappings)
-               return 0;
-
-       map_end = nd_mapping->start + nd_mapping->size - 1;
-       if (info->res->start >= nd_mapping->start
-                       && info->res->start < map_end) {
-               if (info->res->end <= map_end) {
-                       info->busy = 0;
-                       return 1;
-               } else {
-                       info->busy -= info->res->end - map_end;
-                       return 0;
-               }
-       } else if (info->res->end >= nd_mapping->start
-                       && info->res->end <= map_end) {
-               info->busy -= nd_mapping->start - info->res->start;
-               return 0;
-       } else {
-               info->busy -= nd_mapping->size;
-               return 0;
-       }
-}
-
 /**
  * nd_blk_available_dpa - account the unused dpa of BLK region
  * @nd_mapping: container of dpa-resource-root + labels
@@ -545,11 +494,7 @@ resource_size_t nd_blk_available_dpa(struct nd_region *nd_region)
        for_each_dpa_resource(ndd, res) {
                if (strncmp(res->name, "blk", 3) != 0)
                        continue;
-
-               info.res = res;
-               info.busy = resource_size(res);
-               device_for_each_child(&nvdimm_bus->dev, &info, blk_dpa_busy);
-               info.available -= info.busy;
+               info.available -= resource_size(res);
        }
 
        return info.available;
index 9690beb15e69ab47bb04345da5f142ec56141035..d996ca73d3be37c2332352fdc45767e738d72822 100644 (file)
@@ -2023,7 +2023,7 @@ nvme_fc_configure_admin_queue(struct nvme_fc_ctrl *ctrl)
        }
 
        ctrl->ctrl.sqsize =
-               min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize);
+               min_t(int, NVME_CAP_MQES(ctrl->cap), ctrl->ctrl.sqsize);
 
        error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap);
        if (error)
index 47a479f26e5d7de3605c0263d1a0cdbba1b7e1c1..16f84eb0b95e8608b73b196763f8bbd886087b22 100644 (file)
@@ -1606,7 +1606,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)
        }
 
        ctrl->ctrl.sqsize =
-               min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize);
+               min_t(int, NVME_CAP_MQES(ctrl->cap), ctrl->ctrl.sqsize);
 
        error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap);
        if (error)
index 22f7bc6bac7fa77dd48198cde3a31ef60ead531b..c7b0b6a527083f7d865e752c7e953b2e1411b808 100644 (file)
@@ -392,7 +392,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
        }
 
        ctrl->ctrl.sqsize =
-               min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize);
+               min_t(int, NVME_CAP_MQES(ctrl->cap), ctrl->ctrl.sqsize);
 
        error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap);
        if (error)
index f80134e3e0b68aba9f8b94771702cdd3df83a678..9ff790174906e46962ec9b9fa00f4f04de14aa18 100644 (file)
--- a/