[Bug 85421] radeon stalled, GPU lockup, reset and failed on resume; crashed by firefox.

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=85421

--- Comment #6 from Hin-Tak Leung  ---
(In reply to Alex Deucher from comment #5)
> Just try a newer or older version and see if it helps.  If so, try and
> bisect to narrow down what change on the mesa side cuased the problem.

Unfortunately it doesn't happen often/"reproducible" enough to do git bisect...
This is a new machine/hardware which I just put linux on exactly a month ago,
and things stabilising perhaps around when I put mesa 10.2.8 on on 25th sept.
It is my "main" machine now, and locked up twice in 18 days, which is frequent
enough to be troublesome but not frequent enough to do bisect/go back/forward
versions to try...

I do think it is a kernel problem though, as it seems to be accompanied by X
and gnome-shell segfaulting. I still have the core dump from X if that helps?

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


v3.17, i915 vs nouveau: possible recursive locking detected

2014-10-13 Thread Marcin Ĺšlusarz
=
[ INFO: possible recursive locking detected ]
3.17.0 #50 Not tainted
-
Xorg/1170 is trying to acquire lock:
 (>struct_mutex){+.+.+.}, at: [] 
i915_gem_unmap_dma_buf+0x33/0xc0 [i915]

but task is already holding lock:
 (>struct_mutex){+.+.+.}, at: [] 
drm_gem_object_handle_unreference_unlocked+0xca/0x120 [drm]

other info that might help us debug this:
 Possible unsafe locking scenario:

   CPU0
   
  lock(>struct_mutex);
  lock(>struct_mutex);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

1 lock held by Xorg/1170:
 #0:  (>struct_mutex){+.+.+.}, at: [] 
drm_gem_object_handle_unreference_unlocked+0xca/0x120 [drm]

stack backtrace:
CPU: 1 PID: 1170 Comm: Xorg Not tainted 3.17.0 #50
Hardware name: Dell Inc.  Inspiron 7720/04M3YM, BIOS A07 08/16/2012
 82606b80 880136e27b00 81707891 82606b80
 880136e27bb8 810e0e4f  00020200c795
 0001  004ec276 0300
Call Trace:
 [] dump_stack+0x4e/0x7a
 [] __lock_acquire+0x194f/0x19e0
 [] lock_acquire+0x91/0x120
 [] ? i915_gem_unmap_dma_buf+0x33/0xc0 [i915]
 [] ? i915_gem_unmap_dma_buf+0x33/0xc0 [i915]
 [] mutex_lock_nested+0x54/0x3d0
 [] ? i915_gem_unmap_dma_buf+0x33/0xc0 [i915]
 [] ? mark_held_locks+0x6a/0x90
 [] i915_gem_unmap_dma_buf+0x33/0xc0 [i915]
 [] dma_buf_unmap_attachment+0x22/0x40
 [] drm_prime_gem_destroy+0x22/0x40 [drm]
 [] nouveau_gem_object_del+0x3b/0x60 [nouveau]
 [] drm_gem_object_free+0x27/0x30 [drm]
 [] drm_gem_object_handle_unreference_unlocked+0xe4/0x120 
[drm]
 [] drm_gem_handle_delete+0xba/0x110 [drm]
 [] drm_gem_close_ioctl+0x25/0x30 [drm]
 [] drm_ioctl+0x1ec/0x660 [drm]
 [] ? __pm_runtime_resume+0x32/0x60
 [] ? _raw_spin_unlock_irqrestore+0x5d/0x70
 [] ? trace_hardirqs_on_caller+0xfd/0x1c0
 [] ? trace_hardirqs_on+0xd/0x10
 [] ? _raw_spin_unlock_irqrestore+0x42/0x70
 [] nouveau_drm_ioctl+0x54/0xc0 [nouveau]
 [] do_vfs_ioctl+0x300/0x520
 [] ? __fget+0xad/0xe0
 [] ? __fget+0x5/0xe0
 [] SyS_ioctl+0x81/0xa0
 [] system_call_fastpath+0x1a/0x1f


[PATCH] drm/nouveau/disp: Use NULL for pointers

2014-10-13 Thread Emil Velikov
On 13/10/14 12:47, Thierry Reding wrote:
> On Mon, Jul 21, 2014 at 02:02:58PM +0200, Thierry Reding wrote:
>> From: Thierry Reding 
>>
>> The return type of exec_lookup() is struct nvkm_output *, so it should
>> return NULL rather than 0.
>>
>> Signed-off-by: Thierry Reding 
>> ---
>>  drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c 
>> b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
>> index fa30d8196f35..ebf64e1d0a70 100644
>> --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
>> +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
>> @@ -939,7 +939,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int 
>> or, u32 ctrl,
>>  case 0x0900: type = DCB_OUTPUT_DP; mask = 2; break;
>>  default:
>>  nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
>> -return 0x;
>> +return NULL;
>>  }
>>  }
>>  
> 
> Ping?
> 
> Thierry
> 
I have an identical patch in a local branch, but with worse commit
message :) Fwiw the patch is

Reviewed-by: Emil Velikov 

-Emil



[RFC PATCH 3/3] libdrm: user mode helper for ipvr drm driver

2014-10-13 Thread Yao Cheng
usermode helper of ipvr drm driver.
test tools:
1. test_ioctl: test kernel driver by directly ioctl
2. test_decode: test decode functionality by calling libdrm_ipvr

Signed-off-by: Yao Cheng 
---
 Makefile.am|6 +-
 Makefile.sources   |1 +
 configure.ac   |   26 +-
 include/drm/ipvr_drm.h |  268 ++
 ipvr/Makefile.am   |   58 +
 ipvr/Makefile.sources  |5 +
 ipvr/ipvr_bufmgr.h |  156 ++
 ipvr/ipvr_bufmgr_gem.c | 1857 +
 ipvr/libdrm_ipvr.pc.in |   11 +
 ipvr/test_decode.c | 6807 
 ipvr/test_ioctl.c  |  323 +++
 11 files changed, 9516 insertions(+), 2 deletions(-)
 create mode 100644 include/drm/ipvr_drm.h
 create mode 100644 ipvr/Makefile.am
 create mode 100644 ipvr/Makefile.sources
 create mode 100644 ipvr/ipvr_bufmgr.h
 create mode 100644 ipvr/ipvr_bufmgr_gem.c
 create mode 100644 ipvr/libdrm_ipvr.pc.in
 create mode 100644 ipvr/test_decode.c
 create mode 100644 ipvr/test_ioctl.c

diff --git a/Makefile.am b/Makefile.am
index 3952a88..2227add 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,6 +33,10 @@ if HAVE_INTEL
 INTEL_SUBDIR = intel
 endif

+if HAVE_IPVR
+IPVR_SUBDIR = ipvr
+endif
+
 if HAVE_NOUVEAU
 NOUVEAU_SUBDIR = nouveau
 endif
@@ -53,7 +57,7 @@ if HAVE_FREEDRENO
 FREEDRENO_SUBDIR = freedreno
 endif

-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) 
$(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests man
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(IPVR_SUBDIR) $(NOUVEAU_SUBDIR) 
$(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests man

 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
diff --git a/Makefile.sources b/Makefile.sources
index d86fb2a..96f8c60 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -18,6 +18,7 @@ LIBDRM_INCLUDE_H_FILES := \
include/drm/drm_mode.h \
include/drm/drm_sarea.h \
include/drm/i915_drm.h \
+   include/drm/ipvr_drm.h \
include/drm/mach64_drm.h \
include/drm/mga_drm.h \
include/drm/nouveau_drm.h \
diff --git a/configure.ac b/configure.ac
index ee59b03..6dcf1b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,6 +68,11 @@ AC_ARG_ENABLE(intel,
  [Enable support for intel's KMS API (default: auto)]),
  [INTEL=$enableval], [INTEL=auto])

+AC_ARG_ENABLE(ipvr,
+ AS_HELP_STRING([--disable-ipvr],
+ [Enable support for baytrail's hardware VP8 decode (default: 
auto)]),
+ [IPVR=$enableval], [IPVR=auto])
+
 AC_ARG_ENABLE(radeon,
  AS_HELP_STRING([--disable-radeon],
  [Enable support for radeon's KMS API (default: auto)]),
@@ -204,7 +209,7 @@ if test "x$drm_cv_atomic_primitives" = "xlibatomic-ops"; 
then
AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, [Enable if you have libatomic-ops-dev 
installed])
 fi

-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno"; then
+if test "x$INTEL" != "xno" -o "x$IPVR" != "xno" -o "x$RADEON" != "xno" -o 
"x$NOUVEAU" != "xno"; then
if test "x$drm_cv_atomic_primitives" = "xnone"; then
if test "x$INTEL" != "xauto"; then
if test "x$INTEL" != "xno"; then
@@ -214,6 +219,14 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o 
"x$NOUVEAU" != "xno"; then
AC_MSG_WARN([Disabling libdrm_intel. It depends on 
atomic operations, which were not found for your compiler/cpu. Try compiling 
with -march=native, or install the libatomics-op-dev package.])
INTEL=no
fi
+   if test "x$IPVR" != "xauto"; then
+   if test "x$IPVR" != "xno"; then
+   AC_MSG_ERROR([libdrm_ipvr depends upon atomic 
operations, which were not found for your compiler/cpu. Try compiling with 
-march=native, or install the libatomics-op-dev package, or, failing both of 
those, disable support for Baytrail VP8 by passing --disable-ipvr to 
./configure])
+   fi
+   else
+   AC_MSG_WARN([Disabling libdrm_ipvr. It depends on 
atomic operations, which were not found for your compiler/cpu. Try compiling 
with -march=native, or install the libatomics-op-dev package.])
+   INTEL=no
+   fi
if test "x$RADEON" != "xauto"; then
if test "x$RADEON" != "xno"; then
AC_MSG_ERROR([libdrm_radeon depends upon atomic 
operations, which were not found for your compiler/cpu. Try compiling with 
-march=native, or install the libatomics-op-dev package, or, failing both of 
those, disable support for Radeon GPUs by passing --disable-radeon to 
./configure])
@@ -237,6 +250,9 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o 
"x$NOUVEAU" != "xno"; then
*) INTEL=no ;;
esac
fi
+  

[RFC PATCH 2/3] drm/ipvr: drm driver for vxd392

2014-10-13 Thread Yao Cheng
Probes vxd392 on Baytrail platform and create
a new drm device for hardware accelerated video
decoding.

Signed-off-by: Yao Cheng 
---
 drivers/gpu/drm/Kconfig|2 +
 drivers/gpu/drm/Makefile   |1 +
 drivers/gpu/drm/ipvr/Kconfig   |   16 +
 drivers/gpu/drm/ipvr/Makefile  |   21 +
 drivers/gpu/drm/ipvr/ipvr_buffer.c | 1177 +
 drivers/gpu/drm/ipvr/ipvr_buffer.h |  184 ++
 drivers/gpu/drm/ipvr/ipvr_debug.c  |  263 
 drivers/gpu/drm/ipvr/ipvr_debug.h  |   50 ++
 drivers/gpu/drm/ipvr/ipvr_drm.h|  265 
 drivers/gpu/drm/ipvr/ipvr_drv.c|  776 ++
 drivers/gpu/drm/ipvr/ipvr_drv.h|  464 +
 drivers/gpu/drm/ipvr/ipvr_exec.c   |  530 +++
 drivers/gpu/drm/ipvr/ipvr_exec.h   |   68 ++
 drivers/gpu/drm/ipvr/ipvr_fence.c  |  550 
 drivers/gpu/drm/ipvr/ipvr_fence.h  |   68 ++
 drivers/gpu/drm/ipvr/ipvr_gem.c|  248 +++
 drivers/gpu/drm/ipvr/ipvr_gem.h|   66 ++
 drivers/gpu/drm/ipvr/ipvr_mmu.c|  807 +++
 drivers/gpu/drm/ipvr/ipvr_mmu.h|  135 
 drivers/gpu/drm/ipvr/ipvr_trace.c  |   11 +
 drivers/gpu/drm/ipvr/ipvr_trace.h  |  296 +
 drivers/gpu/drm/ipvr/ved_cmd.c | 1269 
 drivers/gpu/drm/ipvr/ved_cmd.h |  104 +++
 drivers/gpu/drm/ipvr/ved_ec.c  |  584 +
 drivers/gpu/drm/ipvr/ved_ec.h  |  207 ++
 drivers/gpu/drm/ipvr/ved_fw.c  |  660 +++
 drivers/gpu/drm/ipvr/ved_fw.h  |   73 +++
 drivers/gpu/drm/ipvr/ved_init.c|  829 +++
 drivers/gpu/drm/ipvr/ved_init.h|   61 ++
 drivers/gpu/drm/ipvr/ved_msg.h |  364 +++
 drivers/gpu/drm/ipvr/ved_pm.c  |  392 +++
 drivers/gpu/drm/ipvr/ved_pm.h  |   55 ++
 drivers/gpu/drm/ipvr/ved_reg.h |  609 +
 33 files changed, 11205 insertions(+)
 create mode 100644 drivers/gpu/drm/ipvr/Kconfig
 create mode 100644 drivers/gpu/drm/ipvr/Makefile
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_buffer.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_buffer.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_debug.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_debug.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_drm.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_drv.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_drv.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_exec.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_exec.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_fence.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_fence.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_gem.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_gem.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_mmu.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_mmu.h
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_trace.c
 create mode 100644 drivers/gpu/drm/ipvr/ipvr_trace.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_cmd.c
 create mode 100644 drivers/gpu/drm/ipvr/ved_cmd.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_ec.c
 create mode 100644 drivers/gpu/drm/ipvr/ved_ec.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_fw.c
 create mode 100644 drivers/gpu/drm/ipvr/ved_fw.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_init.c
 create mode 100644 drivers/gpu/drm/ipvr/ved_init.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_msg.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_pm.c
 create mode 100644 drivers/gpu/drm/ipvr/ved_pm.h
 create mode 100644 drivers/gpu/drm/ipvr/ved_reg.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index e3b4b0f..ad7585d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -165,6 +165,8 @@ config DRM_SAVAGE
  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
  chipset. If M is selected the module will be called savage.

+source "drivers/gpu/drm/ipvr/Kconfig"
+
 source "drivers/gpu/drm/exynos/Kconfig"

 source "drivers/gpu/drm/vmwgfx/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 9292a76..8ec4bda 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon/
 obj-$(CONFIG_DRM_MGA)  += mga/
 obj-$(CONFIG_DRM_I810) += i810/
 obj-$(CONFIG_DRM_I915)  += i915/
+obj-$(CONFIG_DRM_IPVR)  += ipvr/
 obj-$(CONFIG_DRM_MGAG200) += mgag200/
 obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
 obj-$(CONFIG_DRM_SIS)   += sis/
diff --git a/drivers/gpu/drm/ipvr/Kconfig b/drivers/gpu/drm/ipvr/Kconfig
new file mode 100644
index 000..6516590
--- /dev/null
+++ b/drivers/gpu/drm/ipvr/Kconfig
@@ -0,0 +1,16 @@
+config DRM_IPVR
+   tristate "Baytrail VP8 video decode driver"
+   depends on DRM
+   depends on DRM_I915
+   select SHMEM
+   select TMPFS
+   default m
+   help
+ Choose this option if you want to enable hardware accelerated VP8 
decoding on Baytrail platform
+
+config DRM_IPVR_EC
+   

[RFC PATCH 1/3] drm/i915: add vxd392 bridge in i915

2014-10-13 Thread Yao Cheng
Setup following resources during i915_driver_load:
1. create a child platform and resource
2. allocate a new IRQ line and irq chip
3. set up IRQ mask/unmask callbacks
vxd392 driver (if installed) will bind itself to the
platform device and create new drm device

Signed-off-by: Yao Cheng 
---
 drivers/gpu/drm/i915/i915_dma.c   | 98 +++
 drivers/gpu/drm/i915/i915_drv.h   |  6 +++
 drivers/gpu/drm/i915/i915_irq.c   | 70 
 drivers/gpu/drm/i915/i915_reg.h   |  4 ++
 drivers/gpu/drm/i915/i915_trace.h | 15 ++
 5 files changed, 193 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 85d14e1..73c78d1 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -85,6 +85,96 @@ intel_read_legacy_status_page(struct drm_i915_private 
*dev_priv, int reg)
 #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
 #define I915_BREADCRUMB_INDEX  0x21

+static int valleyview_ved_init(struct drm_device *dev)
+{
+   int ret;
+   int irq = -1;
+   struct resource *rsc = NULL;
+   struct drm_i915_private *dev_priv = dev->dev_private;;
+
+   dev_priv->ved_platdev = platform_device_alloc("ipvr-ved", -1);
+   if (unlikely(!dev_priv->ved_platdev)) {
+   DRM_ERROR("Failed to allocate VED platform device\n");
+   ret = -ENOMEM;
+   goto err;
+   }
+
+   rsc = kzalloc(sizeof(*rsc) * 3, GFP_KERNEL);
+   if (unlikely(!rsc)) {
+   DRM_ERROR("Failed to allocate resource for VED platform 
device\n");
+   ret = -ENOMEM;
+   goto err;
+   }
+
+   /* init IRQ number and chip/callbacks */
+   irq = irq_alloc_descs(-1, 0, 1, 0);
+   if (unlikely(irq < 0)) {
+   DRM_ERROR("Failed to allocate IRQ number: %d\n", irq);
+   ret = -ENOMEM;
+   goto err;
+   }
+
+   ret = valleyview_initialize_ved_irq(dev, irq);
+   if (unlikely(ret)) {
+   DRM_ERROR("Failed to initialize VED IRQ: %d\n", ret);
+   goto err;
+   }
+
+   dev_priv->ved_irq = irq;
+   rsc[0].start= rsc[0].end = irq;
+   rsc[0].flags= IORESOURCE_IRQ;
+   rsc[0].name = "ipvr-ved-irq";
+
+   /* MMIO/REG for child's use */
+   rsc[1].start= pci_resource_start(dev->pdev, 0);
+   rsc[1].end  = pci_resource_start(dev->pdev, 0) + 2*1024*1024; /* 
gen7 */
+   rsc[1].flags= IORESOURCE_MEM;
+   rsc[1].name = "ipvr-ved-mmio";
+
+   rsc[2].start= VLV_VED_BASE;
+   rsc[2].end  = VLV_VED_BASE + VLV_VED_SIZE;
+   rsc[2].flags= IORESOURCE_REG;
+   rsc[2].name = "ipvr-ved-reg";
+
+   ret = platform_device_add_resources(dev_priv->ved_platdev, rsc, 3);
+   if (unlikely(ret)) {
+   DRM_ERROR("Failed to add resource for VED platform device: 
%d\n", ret);
+   goto err;
+   }
+
+   /* Runtime-PM hook */
+   dev_priv->ved_platdev->dev.parent = dev->dev;
+   ret = platform_device_add(dev_priv->ved_platdev);
+   if (unlikely(ret)) {
+   DRM_ERROR("Failed to add VED platform device: %d\n", ret);
+   goto err;
+   }
+
+   kfree(rsc);
+   DRM_INFO("Successfully initialized Valleyview-VED\n");
+   return 0;
+err:
+   if (rsc)
+   kfree(rsc);
+   if (dev_priv->ved_platdev)
+   platform_device_unregister(dev_priv->ved_platdev);
+   if (irq >= 0)
+   irq_free_desc(irq);
+   return ret;
+}
+
+static void valleyview_ved_cleanup(struct drm_device *dev)
+{
+   int irq;
+   struct drm_i915_private *dev_priv = dev->dev_private;
+
+   irq = platform_get_irq(dev_priv->ved_platdev, 0);
+   if (irq >= 0)
+   irq_free_desc(irq);
+
+   platform_device_unregister(dev_priv->ved_platdev);
+}
+
 void i915_update_dri1_breadcrumb(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1793,6 +1883,10 @@ int i915_driver_load(struct drm_device *dev, unsigned 
long flags)

intel_runtime_pm_enable(dev_priv);

+   if (IS_VALLEYVIEW(dev)) {
+   BUG_ON(valleyview_ved_init(dev));
+   }
+
return 0;

 out_power_well:
@@ -1833,6 +1927,10 @@ int i915_driver_unload(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;

+   if (IS_VALLEYVIEW(dev)) {
+   valleyview_ved_cleanup(dev);
+   }
+
ret = i915_gem_suspend(dev);
if (ret) {
DRM_ERROR("failed to idle hardware: %d\n", ret);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 821ba26..aa8a183 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1709,6 +1709,10 @@ struct drm_i915_private {

uint32_t bios_vgacntr;

+   /* 

[RFC PATCH 0/3] drm driver for baytrail's vxd392

2014-10-13 Thread Yao Cheng
drm/ipvr is a new GEM driver for baytrail's vxd392, which accelerates VP8 video 
decoding.
The driver name "ipvr" means the PowerVR's IP wrapped by Intel. In the future, 
ipvr may support other platforms such as Merrifield.
Code is placed at drivers/gpu/drm/ipvr and the following two new Kconfig are 
added:
  CONFIG_DRM_IPVR: Build option for ipvr module
  CONFIG_DRM_IPVR_EC: Experimental feature of error concealment

User mode drm helper "libdrm_ipvr.so" and simple test are also included.

Yao Cheng (3):
 [1/3] drm/i915: add vxd392 bridge in i915 on baytrail
 [2/3] drm/ipvr: ipvr drm driver for vxd392
 [3/3] libdrm: user mode helper for ipvr drm driver

-- 
1.9.1



[Bug 86181] Timeout setting UVD clocks

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=86181

--- Comment #1 from sterfield at gmail.com ---
Created attachment 153561
  --> https://bugzilla.kernel.org/attachment.cgi?id=153561=edit
lspci of my graphic card

lspci -vvv of my graphic card.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 86181] New: Timeout setting UVD clocks

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=86181

Bug ID: 86181
   Summary: Timeout setting UVD clocks
   Product: Drivers
   Version: 2.5
Kernel Version: 3.16.3-2
  Hardware: All
OS: Linux
  Tree: Mainline
Status: NEW
  Severity: normal
  Priority: P1
 Component: Video(DRI - non Intel)
  Assignee: drivers_video-dri at kernel-bugs.osdl.org
  Reporter: sterfield at gmail.com
Regression: No

Created attachment 153551
  --> https://bugzilla.kernel.org/attachment.cgi?id=153551=edit
full dmesg

Hi,

I've bought recently a MSI R7 265 (lspci attached), and use it in build under
Debian testing.

I've tried to configure it in order to have H264 hardware decoding, but UVD
failed at boot time (dmesg attached).

I've tried to boot with dpm=0, the problem is still here.

As one user had problem with maybe overheating
(https://bugzilla.kernel.org/show_bug.cgi?id=60858), I changed the thermal
paste on my graphic card, but the problem persists.

I've dumped some registers, as it seems to be interesting :

root at steambox:~# radeontool regmatch 0x0718
0x0718  0x0023 (35)
root at steambox:~# radeontool regmatch 0x071c
0x071c  0xc080001c (-1065353188)
root at steambox:~# radeontool regmatch 0x0720
0x0720  0x3168680e (828925966)

Thanks for your help !

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 84836] VERDE lockup with Unigine Valley/Heaven if ARB_sample_shading is enabled

2014-10-13 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=84836

--- Comment #4 from Alexander Tsoy  ---
(In reply to Marek Ol??k from comment #3)
> I think you forgot to install drirc from Mesa. What happens if you set this
> env var?

No, I have correct drirc.

> 
> allow_glsl_extension_directive_midshader=true

Setting this env variable doesn't help.


(In reply to Michel D?nzer from comment #1)

> Can you try a newer kernel?

I just tried 3.17.0:

- GPU still hangs if ARB_sample_shading is not disabled.

- It seems lockup detection timeout was increased significantly:

kernel: radeon :01:00.0: ring 0 stalled for more than 91985msec
kernel: radeon :01:00.0: GPU lockup (waiting for 0xe90a last
fence id 0xe8fb on ring 0)

- Unrelated to this bug, but.. animation is VERY choppy. I constantly see
several-seconds-long freezes, and sometimes >10 sec long freezes.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/ebe30985/attachment.html>


[PATCH] drm: drm_err: Remove unnecessary __func__ argument

2014-10-13 Thread David Herrmann
Hi

On Sun, Oct 12, 2014 at 7:08 AM, Joe Perches  wrote:
> Removing the unnecessary drm_err __func__ argument by using
> the equivalent %pf and __builtin_return_address(0) makes the
> code smaller for every use of the DRM_ERROR macro.
>
> For instance: (allmodconfig)
>
> $ size drivers/gpu/drm/i915/i915.o*
>textdata bss dec hex filename
>  922447  193257  296736 1412440  158d58 drivers/gpu/drm/i915/i915.o.new
>  928111  193257  296736 1418104  15a378 drivers/gpu/drm/i915/i915.o.old

You might want to mention that this requires a binary-search through
kallsyms on each call. I guess that's the reason you didn't use it for
drm_ut_debug_printk()? I'm fine with doing this on drm_err(). Looks
good.

Thanks
David

> Signed-off-by: Joe Perches 
> ---
>  drivers/gpu/drm/drm_drv.c | 5 +++--
>  include/drm/drmP.h| 8 
>  2 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 9f0e1b9..e9263d9 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -68,7 +68,7 @@ static struct idr drm_minors_idr;
>  struct class *drm_class;
>  static struct dentry *drm_debugfs_root;
>
> -void drm_err(const char *func, const char *format, ...)
> +void drm_err(const char *format, ...)
>  {
> struct va_format vaf;
> va_list args;
> @@ -78,7 +78,8 @@ void drm_err(const char *func, const char *format, ...)
> vaf.fmt = format;
> vaf.va = 
>
> -   printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, );
> +   printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV",
> +  __builtin_return_address(0), );
>
> va_end(args);
>  }
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index ca374ac..5e9ff52 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -125,8 +125,8 @@ struct reservation_object;
>  extern __printf(2, 3)
>  void drm_ut_debug_printk(const char *function_name,
>  const char *format, ...);
> -extern __printf(2, 3)
> -void drm_err(const char *func, const char *format, ...);
> +extern __printf(1, 2)
> +void drm_err(const char *format, ...);
>
>  /***/
>  /** \name DRM template customization defaults */
> @@ -168,7 +168,7 @@ void drm_err(const char *func, const char *format, ...);
>   * \param arg arguments
>   */
>  #define DRM_ERROR(fmt, ...)\
> -   drm_err(__func__, fmt, ##__VA_ARGS__)
> +   drm_err(fmt, ##__VA_ARGS__)
>
>  /**
>   * Rate limited error output.  Like DRM_ERROR() but won't flood the log.
> @@ -183,7 +183,7 @@ void drm_err(const char *func, const char *format, ...);
>   DEFAULT_RATELIMIT_BURST); \
> \
> if (__ratelimit(&_rs))  \
> -   drm_err(__func__, fmt, ##__VA_ARGS__);  \
> +   drm_err(fmt, ##__VA_ARGS__);\
>  })
>
>  #define DRM_INFO(fmt, ...) \
>
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[Bug 83731] dpm still not working on radeon TURKS 1002:6840

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=83731

Alex Deucher  changed:

   What|Removed |Added

 CC||alexdeucher at gmail.com

--- Comment #2 from Alex Deucher  ---
Does it work properly with radeon.runpm=0

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 82889] [drm:si_dpm_set_power_state] *ERROR* si_disable_ulv failed

2014-10-13 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=82889

--- Comment #17 from Alex Deucher  ---
Created attachment 107784
  --> https://bugs.freedesktop.org/attachment.cgi?id=107784=edit
disable ulv state on SI

(In reply to Alexandre Demers from comment #16)
> Alex, I think this "ERROR" should be at most a warning: I've been commenting
> out the "return ret" when we hit the error, and everything else goes as
> smooth as possible.
> 
> Also, do you have any clue on the way we should dig to understand why we are
> hitting this error? As said by Samir, this appeared with dpm.

It's part of dpm so it only happens when dpm is enabled.  ulv is a special low
power state the card can go to in certain idle cases.

Does the attached patch help?

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/1032112d/attachment-0001.html>


[Bug 85421] radeon stalled, GPU lockup, reset and failed on resume; crashed by firefox.

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=85421

--- Comment #5 from Alex Deucher  ---
(In reply to Hin-Tak Leung from comment #4)
> (In reply to Alex Deucher from comment #3)
> > GPU lockups are usually caused by a problem with the command buffers
> > generated in the usermode acceleration drivers in mesa.  I would suggest
> > trying a newer version of mesa.
> 
> How recent should I try? I am already using mesa 10.2.8 and libdrm 2.4.58 .
> libdrm seems to be a more recent install on 5th Oct, both mesa 10.2.8 was
> already on when the lock-up happened (twice). mesa 10.3 was released around
> the same time as 10.2.8 .

Just try a newer or older version and see if it helps.  If so, try and bisect
to narrow down what change on the mesa side cuased the problem.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[RFC PATCH 2/3] drm/ipvr: drm driver for vxd392

2014-10-13 Thread David Herrmann
Hi

> +static struct drm_ioctl_desc ipvr_gem_ioctls[] = {
> +   DRM_IOCTL_DEF_DRV(IPVR_CONTEXT_CREATE,
> +   ipvr_context_create_ioctl, DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_CONTEXT_DESTROY,
> +   ipvr_context_destroy_ioctl, DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_MISC,
> +   ipvr_misc_ioctl, DRM_AUTH),
> +   DRM_IOCTL_DEF_DRV(IPVR_GEM_EXECBUFFER,
> +   ipvr_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_GEM_BUSY,
> +   ipvr_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_GEM_CREATE,
> +   ipvr_gem_create_ioctl, DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_GEM_MMAP,
> +   ipvr_gem_mmap_ioctl, DRM_UNLOCKED),

Why do you need this ioctl? mmap() should work perfectly fine. I don't
see why you require people to use a ipvr specific ioctl to map
buffers.

> +   DRM_IOCTL_DEF_DRV(IPVR_SYNC_CPU,
> +   ipvr_sync_cpu_ioctl, DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_GEM_WAIT,
> +   ipvr_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +   DRM_IOCTL_DEF_DRV(IPVR_GEM_USERPTR,
> +   ipvr_gem_userptr_ioctl, DRM_UNLOCKED),
> +};
> +
> +static void ipvr_gem_init(struct drm_device *dev)
> +{
> +   struct drm_ipvr_private *dev_priv = dev->dev_private;
> +
> +   dev_priv->ipvr_bo_slab = kmem_cache_create("ipvr_gem_object",
> + sizeof(union drm_ipvr_gem_objects), 0,
> + SLAB_HWCACHE_ALIGN, NULL);
> +
> +   INIT_LIST_HEAD(_priv->ipvr_mm.unbound_list);
> +   INIT_LIST_HEAD(_priv->ipvr_mm.bound_list);
> +   spin_lock_init(_priv->ipvr_mm.object_stat_lock);
> +
> +   dev_priv->ipvr_mm.interruptible = true;
> +}
> +
> +static void ipvr_gem_setup_mmu(struct drm_device *dev,
> +  unsigned long linear_start,
> +  unsigned long linear_end,
> +  unsigned long tiling_start,
> +  unsigned long tiling_end)
> +{
> +   /* Let GEM Manage all of the aperture.
> +*
> +* However, leave one page at the end still bound to the scratch page.
> +* There are a number of places where hardware apparently prefetches
> +* past the end of the object, and we've seen multiple hangs with the
> +* GPU head pointer stuck in a batchbuffer bound at last page of the
> +* aperture.  One page should be enough to keep any prefetching inside
> +* of the aperture.
> +*/
> +   struct drm_ipvr_private *dev_priv = dev->dev_private;
> +   struct ipvr_address_space *addr_space = _priv->addr_space;
> +
> +   /* todo: add sanity check */
> +   addr_space->dev = dev_priv->dev;
> +   INIT_LIST_HEAD(_space->active_list);
> +   INIT_LIST_HEAD(_space->inactive_list);
> +
> +   /* Subtract the guard page ... */
> +   drm_mm_init(_space->linear_mm, linear_start,
> +   linear_end - linear_start - PAGE_SIZE);
> +   dev_priv->addr_space.linear_start = linear_start;
> +   dev_priv->addr_space.linear_total = linear_end - linear_start;
> +
> +   drm_mm_init(_space->tiling_mm, tiling_start,
> +   tiling_end - tiling_start - PAGE_SIZE);
> +   dev_priv->addr_space.tiling_start = tiling_start;
> +   dev_priv->addr_space.tiling_total = tiling_end - tiling_start;
> +}
> +
> +static void ipvr_do_takedown(struct drm_device *dev)
> +{
> +   /* todo: need check if need clean up mm here */
> +   ipvr_ved_uninit(dev);
> +}
> +
> +static int32_t ipvr_drm_unload(struct drm_device *dev)
> +{
> +   struct drm_ipvr_private *dev_priv = dev->dev_private;
> +
> +   BUG_ON(!dev->platformdev);
> +   BUG_ON(atomic_read(_priv->ved_power_usage));
> +
> +   IPVR_DEBUG_ENTRY("entered.");
> +   if (dev_priv) {
> +   WARN_ON(pm_runtime_get_sync(>platformdev->dev) < 0);
> +
> +   if (dev_priv->ipvr_bo_slab)
> +   kmem_cache_destroy(dev_priv->ipvr_bo_slab);
> +   ipvr_fence_driver_fini(dev_priv);
> +
> +   ipvr_do_takedown(dev);
> +
> +   WARN_ON(pm_runtime_put_sync_suspend(>platformdev->dev) < 
> 0);
> +
> +   if (dev_priv->validate_ctx.buffers)
> +   vfree(dev_priv->validate_ctx.buffers);
> +
> +   if (dev_priv->pf_pd) {
> +   ipvr_mmu_free_pagedir(dev_priv->pf_pd);
> +   dev_priv->pf_pd = NULL;
> +   }
> +   if (dev_priv->mmu) {
> +   ipvr_mmu_driver_takedown(dev_priv->mmu);
> +   dev_priv->mmu = NULL;
> +   }
> +
> +   if (dev_priv->ved_reg_base) {
> +   

[PATCH 03/15] drm/dsi: Add mipi_dsi_set_maximum_return_packet_size() helper

2014-10-13 Thread Andrzej Hajda
On 10/13/2014 12:16 PM, Thierry Reding wrote:
> +int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
> + u16 value)
> +{
> + u8 tx[2] = { value & 0xff, value >> 8 };
> + struct mipi_dsi_msg msg;
> + ssize_t err;
> +
> + memset(, 0, sizeof(msg));
> + msg.channel = dsi->channel;
> + msg.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE;
> + msg.tx_len = sizeof(tx);
> + msg.tx_buf = tx;

One more thing, why do not use initializer:
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
.tx_len = sizeof(tx),
.tx_buf = tx
};


Regards
Andrzej



[PATCH 04/15] drm/panel: s6e8aa0: Use standard MIPI DSI function

2014-10-13 Thread Andrzej Hajda
On 10/13/2014 12:16 PM, Thierry Reding wrote:
> From: Thierry Reding 
> 
> Use the newly introduced mipi_dsi_set_maximum_return_packet_size()
> function to replace an open-coded version.
> 
> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/panel/panel-s6e8aa0.c | 16 ++--
>  1 file changed, 2 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panel/panel-s6e8aa0.c 
> b/drivers/gpu/drm/panel/panel-s6e8aa0.c
> index 0f85a7c37687..c31e2953f290 100644
> --- a/drivers/gpu/drm/panel/panel-s6e8aa0.c
> +++ b/drivers/gpu/drm/panel/panel-s6e8aa0.c
> @@ -800,27 +800,15 @@ static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
>  }
>  
>  static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
> -int size)
> +u16 size)


I guess this whole function should be removed and direct call to
mipi_dsi_set_maximum_return_packet_size should be used.

Regards
Andrzej


>  {
>   struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
> - const struct mipi_dsi_host_ops *ops = dsi->host->ops;
> - u8 buf[] = {size, 0};
> - struct mipi_dsi_msg msg = {
> - .channel = dsi->channel,
> - .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
> - .tx_len = sizeof(buf),
> - .tx_buf = buf
> - };
>   int ret;
>  
>   if (ctx->error < 0)
>   return;
>  
> - if (!ops || !ops->transfer)
> - ret = -EIO;
> - else
> - ret = ops->transfer(dsi->host, );
> -
> + ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
>   if (ret < 0) {
>   dev_err(ctx->dev,
>   "error %d setting maximum return packet size to %d\n",
> 



[PATCH 03/15] drm/dsi: Add mipi_dsi_set_maximum_return_packet_size() helper

2014-10-13 Thread Andrzej Hajda
On 10/13/2014 12:16 PM, Thierry Reding wrote:
> From: YoungJun Cho 
> 
> This function can be used to set the maximum return packet size for a
> MIPI DSI peripheral.
> 
> Signed-off-by: YoungJun Cho 
> [treding: endianess, kerneldoc, return value]
> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/drm_mipi_dsi.c | 30 ++
>  include/drm/drm_mipi_dsi.h |  2 ++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index 1702ffd07986..27fc6dac5e4a 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -198,6 +198,36 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
>  }
>  EXPORT_SYMBOL(mipi_dsi_detach);
>  
> +/*
> + * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of 
> the
> + *the payload in a long packet transmitted from the peripheral back to 
> the
> + *host processor
> + * @dsi: DSI peripheral device
> + * @value: the maximum size of the payload
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
> + u16 value)
> +{
> + u8 tx[2] = { value & 0xff, value >> 8 };
> + struct mipi_dsi_msg msg;
> + ssize_t err;
> +
> + memset(, 0, sizeof(msg));
> + msg.channel = dsi->channel;
> + msg.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE;
> + msg.tx_len = sizeof(tx);
> + msg.tx_buf = tx;


An alternative (without tx variable) could be:

__cpu_to_le16s();
msg.tx_len = sizeof(value);
msg.tx_buf = 

But it is just pico-optimization.


> +
> + err = dsi->host->ops->transfer(dsi->host, );

I guess the sequence:
if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
msg.flags = MIPI_DSI_MSG_USE_LPM;

should be before this callback.

The same should be in all other helpers calling ops->transfer,
so I guess it may be good to move it all to separate function, for
example sth like:
... dsi_transfer(dsi, msg)
{
if (!ops || !ops->transfer)
return -NOSYS;

if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
msg.flags = MIPI_DSI_MSG_USE_LPM;


return ops->transfer(dsi->host, msg);
}

Regards
Andrzej

> + if (err < 0)
> + return err;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
> +
>  /**
>   * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
>   * @dsi: DSI peripheral device
> diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
> index 836cc2b677d0..ef50b5d0de57 100644
> --- a/include/drm/drm_mipi_dsi.h
> +++ b/include/drm/drm_mipi_dsi.h
> @@ -132,6 +132,8 @@ static inline struct mipi_dsi_device 
> *to_mipi_dsi_device(struct device *dev)
>  
>  int mipi_dsi_attach(struct mipi_dsi_device *dsi);
>  int mipi_dsi_detach(struct mipi_dsi_device *dsi);
> +int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
> + u16 value);
>  ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
> const void *data, size_t len);
>  ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
> 



[Bug 85421] radeon stalled, GPU lockup, reset and failed on resume; crashed by firefox.

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=85421

--- Comment #4 from Hin-Tak Leung  ---
(In reply to Alex Deucher from comment #3)
> GPU lockups are usually caused by a problem with the command buffers
> generated in the usermode acceleration drivers in mesa.  I would suggest
> trying a newer version of mesa.

How recent should I try? I am already using mesa 10.2.8 and libdrm 2.4.58 .
libdrm seems to be a more recent install on 5th Oct, both mesa 10.2.8 was
already on when the lock-up happened (twice). mesa 10.3 was released around the
same time as 10.2.8 .

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[PATCH 02/15] drm/dsi: Constify mipi_dsi_msg

2014-10-13 Thread Andrzej Hajda
On 10/13/2014 12:16 PM, Thierry Reding wrote:
> From: Thierry Reding 
> 
> struct mipi_dsi_msg is a read-only structure, drivers should never need
> to modify it. Make this explicit by making all references to the struct
> const.
> 
> Signed-off-by: Thierry Reding 

Acked-by: Andrzej Hajda 

--
Regards
Andrzej

> ---
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +-
>  include/drm/drm_mipi_dsi.h  | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 24741d8758e8..c5f3c76bfac3 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1236,7 +1236,7 @@ static bool exynos_dsi_is_short_dsi_type(u8 type)
>  }
>  
>  static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
> -struct mipi_dsi_msg *msg)
> + const struct mipi_dsi_msg *msg)
>  {
>   struct exynos_dsi *dsi = host_to_dsi(host);
>   struct exynos_dsi_transfer xfer;
> diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
> index ccc3869e137b..836cc2b677d0 100644
> --- a/include/drm/drm_mipi_dsi.h
> +++ b/include/drm/drm_mipi_dsi.h
> @@ -56,7 +56,7 @@ struct mipi_dsi_host_ops {
>   int (*detach)(struct mipi_dsi_host *host,
> struct mipi_dsi_device *dsi);
>   ssize_t (*transfer)(struct mipi_dsi_host *host,
> - struct mipi_dsi_msg *msg);
> + const struct mipi_dsi_msg *msg);
>  };
>  
>  /**
> 



[Bug 85421] radeon stalled, GPU lockup, reset and failed on resume; crashed by firefox.

2014-10-13 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=85421

Alex Deucher  changed:

   What|Removed |Added

 CC||alexdeucher at gmail.com

--- Comment #3 from Alex Deucher  ---
GPU lockups are usually caused by a problem with the command buffers generated
in the usermode acceleration drivers in mesa.  I would suggest trying a newer
version of mesa.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[PATCH v2 01/15] drm/dsi: Make mipi_dsi_dcs_{read,write}() symmetrical

2014-10-13 Thread Andrzej Hajda
Hi Thierry,

On 10/13/2014 12:16 PM, Thierry Reding wrote:
> From: Thierry Reding 
>
> Currently the mipi_dsi_dcs_write() function requires the DCS command
> byte to be embedded within the write buffer whereas mipi_dsi_dcs_read()
> has a separate parameter. Make them more symmetrical by adding an extra
> command parameter to mipi_dsi_dcs_write().

As we discussed before I do not see much symmetry here - dcs read is
a kind of write command with non empty response.
The new function simplifies calls in case write has no arguments,
and it complicates it in other cases.
But the same simplification could be done by just providing inline function,
for example:
static inline ... mipi_dsi_dcs_write_cmd0(dsi, cmd)
{
return mipi_dsi_dcs_write(dsi, , 1);
}

This way we would have simplified calls for commands without arguments
but without complication in other cases.

Anyway as I was not able to not convince you before, I guess I will not
convince you now.
I just recalled my arguments just to show my concerns to other developers.

On the other side as you left the old API I can live with it :)

Below some additional comments.

>
> The S6E8AA0 driver relies on the old asymmetric API and there's concern
> that moving to the new API may be less efficient. Provide a new function
> with the old semantics for those cases and make the S6E8AA0 driver use
> it instead.
>
> Signed-off-by: Thierry Reding 
> ---
> Changes in v2:
> - provide mipi_dsi_dcs_write_buffer() for backwards compatibility
>
>  drivers/gpu/drm/drm_mipi_dsi.c| 127 
> +-
>  drivers/gpu/drm/panel/panel-s6e8aa0.c |   2 +-
>  include/drm/drm_mipi_dsi.h|   6 +-
>  3 files changed, 114 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index eb6dfe52cab2..1702ffd07986 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -199,33 +199,120 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
>  EXPORT_SYMBOL(mipi_dsi_detach);
>  
>  /**
> - * mipi_dsi_dcs_write - send DCS write command
> - * @dsi: DSI device
> - * @data: pointer to the command followed by parameters
> - * @len: length of @data
> + * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
> + * @dsi: DSI peripheral device
> + * @data: buffer containing data to be transmitted
> + * @len: size of transmission buffer
> + *
> + * This function will automatically choose the right data type depending on
> + * the command payload length.
> + *
> + * Return: The number of bytes successfully transmitted or a negative error
> + * code on failure.
>   */
> -ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data,
> - size_t len)
> +ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
> +   const void *data, size_t len)
>  {
> - const struct mipi_dsi_host_ops *ops = dsi->host->ops;
>   struct mipi_dsi_msg msg = {
>   .channel = dsi->channel,
>   .tx_buf = data,
>   .tx_len = len
>   };
>  
> - if (!ops || !ops->transfer)
> + if (!dsi->host->ops || !dsi->host->ops->transfer)
>   return -ENOSYS;
>  
>   switch (len) {
>   case 0:
>   return -EINVAL;
> +
>   case 1:
>   msg.type = MIPI_DSI_DCS_SHORT_WRITE;
>   break;
> +
>   case 2:
>   msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
>   break;
> +
> + default:
> + msg.type = MIPI_DSI_DCS_LONG_WRITE;
> + break;
> + }
> +
> + return dsi->host->ops->transfer(dsi->host, );

It is just nitpick, but why did you replaced ops variable
by multiple dsi->host->ops expressions? I though it is a good
practice to avoid evaluating the same expression multiple times.

> +}
> +EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
> +
> +/**
> + * mipi_dsi_dcs_write() - send DCS write command
> + * @dsi: DSI peripheral device
> + * @cmd: DCS command
> + * @data: buffer containing the command payload
> + * @len: command payload length
> + *
> + * This function will automatically choose the right data type depending on
> + * the command payload length.
> + *
> + * Return: The number of bytes successfully transmitted or a negative error
> + * code on failure.
> + */
> +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
> +const void *data, size_t len)
> +{
> + struct mipi_dsi_msg msg;
> + ssize_t err;
> + size_t size;
> + u8 *tx;
> +
> + if (!dsi->host->ops || !dsi->host->ops->transfer)
> + return -ENOSYS;
> +
> + if (len > 0) {
> + unsigned int offset = 0;
> +
> + /*
> +  * DCS long write packets contain the word count in the header
> +  * bytes 1 and 2 and have a payload containing the DCS command
> +  * byte folowed by word count minus one bytes.
> +   

[PATCH 01/11] drm/radeon: rework vm_flush parameters

2014-10-13 Thread Alex Deucher
On Mon, Oct 13, 2014 at 6:41 AM, Christian K?nig
 wrote:
> From: Christian K?nig 
>
> Use ring structure instead of index and provide vm_id and pd_addr separately.
>
> Signed-off-by: Christian K?nig 

Series is:
Reviewed-by: Alex Deucher 
And applied to my 3.19 tree.

Alex

> ---
>  drivers/gpu/drm/radeon/cik.c | 23 ++-
>  drivers/gpu/drm/radeon/cik_sdma.c| 22 +-
>  drivers/gpu/drm/radeon/ni.c  | 14 +-
>  drivers/gpu/drm/radeon/ni_dma.c  | 14 +-
>  drivers/gpu/drm/radeon/radeon.h  |  5 +++--
>  drivers/gpu/drm/radeon/radeon_asic.h | 18 --
>  drivers/gpu/drm/radeon/radeon_vm.c   |  3 ++-
>  drivers/gpu/drm/radeon/si.c  | 18 +++---
>  drivers/gpu/drm/radeon/si_dma.c  | 19 ---
>  9 files changed, 61 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
> index d48a539..5e58504 100644
> --- a/drivers/gpu/drm/radeon/cik.c
> +++ b/drivers/gpu/drm/radeon/cik.c
> @@ -5958,26 +5958,23 @@ static void cik_vm_decode_fault(struct radeon_device 
> *rdev,
>   * Update the page table base and flush the VM TLB
>   * using the CP (CIK).
>   */
> -void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
> +void cik_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
> + unsigned vm_id, uint64_t pd_addr)
>  {
> -   struct radeon_ring *ring = >ring[ridx];
> -   int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX);
> -
> -   if (vm == NULL)
> -   return;
> +   int usepfp = (ring->idx == RADEON_RING_TYPE_GFX_INDEX);
>
> radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
>  WRITE_DATA_DST_SEL(0)));
> -   if (vm->id < 8) {
> +   if (vm_id < 8) {
> radeon_ring_write(ring,
> - (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id 
> << 2)) >> 2);
> + (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id 
> << 2)) >> 2);
> } else {
> radeon_ring_write(ring,
> - (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + 
> ((vm->id - 8) << 2)) >> 2);
> + (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm_id 
> - 8) << 2)) >> 2);
> }
> radeon_ring_write(ring, 0);
> -   radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
> +   radeon_ring_write(ring, pd_addr >> 12);
>
> /* update SH_MEM_* regs */
> radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> @@ -5985,7 +5982,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, 
> struct radeon_vm *vm)
>  WRITE_DATA_DST_SEL(0)));
> radeon_ring_write(ring, SRBM_GFX_CNTL >> 2);
> radeon_ring_write(ring, 0);
> -   radeon_ring_write(ring, VMID(vm->id));
> +   radeon_ring_write(ring, VMID(vm_id));
>
> radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 6));
> radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
> @@ -6006,7 +6003,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, 
> struct radeon_vm *vm)
> radeon_ring_write(ring, VMID(0));
>
> /* HDP flush */
> -   cik_hdp_flush_cp_ring_emit(rdev, ridx);
> +   cik_hdp_flush_cp_ring_emit(rdev, ring->idx);
>
> /* bits 0-15 are the VM contexts0-15 */
> radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
> @@ -6014,7 +6011,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, 
> struct radeon_vm *vm)
>  WRITE_DATA_DST_SEL(0)));
> radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
> radeon_ring_write(ring, 0);
> -   radeon_ring_write(ring, 1 << vm->id);
> +   radeon_ring_write(ring, 1 << vm_id);
>
> /* compute doesn't have PFP */
> if (usepfp) {
> diff --git a/drivers/gpu/drm/radeon/cik_sdma.c 
> b/drivers/gpu/drm/radeon/cik_sdma.c
> index c473c91..2bc8a2f 100644
> --- a/drivers/gpu/drm/radeon/cik_sdma.c
> +++ b/drivers/gpu/drm/radeon/cik_sdma.c
> @@ -905,25 +905,21 @@ void cik_sdma_vm_pad_ib(struct radeon_ib *ib)
>   * Update the page table base and flush the VM TLB
>   * using sDMA (CIK).
>   */
> -void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm 
> *vm)
> +void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
> + unsigned vm_id, uint64_t pd_addr)
>  {
> -   struct radeon_ring *ring = >ring[ridx];
> -
> -   if (vm == NULL)
> -   return;
> -
> radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 
> 0xf000));
> -   if (vm->id < 8) {
> -   radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + 
> (vm->id << 2)) >> 2);
> +   if (vm_id < 8) {
> +   

[PATCH v2 1/2] drm/radeon: Try placing NO_CPU_ACCESS BOs outside of CPU accessible VRAM

2014-10-13 Thread Alex Deucher
On Thu, Oct 9, 2014 at 11:28 PM, Michel D?nzer  wrote:
> From: Michel D?nzer 
>
> This avoids them getting in the way of BOs which might be accessed by
> the CPU. They can still go to the CPU accessible part of VRAM though if
> there's no space outside of it.
>
> Signed-off-by: Michel D?nzer 

Applied this series to my 3.19 tree.

Alex

> ---
>
> v2: Bump size of struct radeon_bo placements array.
>
>  drivers/gpu/drm/radeon/radeon.h|  2 +-
>  drivers/gpu/drm/radeon/radeon_object.c | 42 
> --
>  2 files changed, 36 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index f7c4b22..11e56ff 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -474,7 +474,7 @@ struct radeon_bo {
> struct list_headlist;
> /* Protected by tbo.reserved */
> u32 initial_domain;
> -   struct ttm_placeplacements[3];
> +   struct ttm_placeplacements[4];
> struct ttm_placementplacement;
> struct ttm_buffer_objecttbo;
> struct ttm_bo_kmap_obj  kmap;
> diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
> b/drivers/gpu/drm/radeon/radeon_object.c
> index 99a960a..7f3b1e1 100644
> --- a/drivers/gpu/drm/radeon/radeon_object.c
> +++ b/drivers/gpu/drm/radeon/radeon_object.c
> @@ -99,22 +99,39 @@ void radeon_ttm_placement_from_domain(struct radeon_bo 
> *rbo, u32 domain)
>
> rbo->placement.placement = rbo->placements;
> rbo->placement.busy_placement = rbo->placements;
> -   if (domain & RADEON_GEM_DOMAIN_VRAM)
> +   if (domain & RADEON_GEM_DOMAIN_VRAM) {
> +   /* Try placing BOs which don't need CPU access outside of the
> +* CPU accessible part of VRAM
> +*/
> +   if ((rbo->flags & RADEON_GEM_NO_CPU_ACCESS) &&
> +   rbo->rdev->mc.visible_vram_size < 
> rbo->rdev->mc.real_vram_size) {
> +   rbo->placements[c].fpfn =
> +   rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
> +   rbo->placements[c++].flags = TTM_PL_FLAG_WC |
> +TTM_PL_FLAG_UNCACHED |
> +TTM_PL_FLAG_VRAM;
> +   }
> +
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_WC |
>  TTM_PL_FLAG_UNCACHED |
>  TTM_PL_FLAG_VRAM;
> +   }
>
> if (domain & RADEON_GEM_DOMAIN_GTT) {
> if (rbo->flags & RADEON_GEM_GTT_UC) {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED |
> TTM_PL_FLAG_TT;
>
> } else if ((rbo->flags & RADEON_GEM_GTT_WC) ||
>(rbo->rdev->flags & RADEON_IS_AGP)) {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_WC |
> TTM_PL_FLAG_UNCACHED |
> TTM_PL_FLAG_TT;
> } else {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_CACHED |
>  TTM_PL_FLAG_TT;
> }
> @@ -122,30 +139,35 @@ void radeon_ttm_placement_from_domain(struct radeon_bo 
> *rbo, u32 domain)
>
> if (domain & RADEON_GEM_DOMAIN_CPU) {
> if (rbo->flags & RADEON_GEM_GTT_UC) {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED |
> TTM_PL_FLAG_SYSTEM;
>
> } else if ((rbo->flags & RADEON_GEM_GTT_WC) ||
> rbo->rdev->flags & RADEON_IS_AGP) {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_WC |
> TTM_PL_FLAG_UNCACHED |
> TTM_PL_FLAG_SYSTEM;
> } else {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_FLAG_CACHED |
>  TTM_PL_FLAG_SYSTEM;
> }
> }
> -   if (!c)
> +   if (!c) {
> +   rbo->placements[c].fpfn = 0;
> rbo->placements[c++].flags = TTM_PL_MASK_CACHING |
>  TTM_PL_FLAG_SYSTEM;
> +   }
>
> rbo->placement.num_placement = c;
> rbo->placement.num_busy_placement = c;
>
> for (i = 0; i < 

[PATCH] drm/ttm: Don't evict BOs outside of the requested placement range

2014-10-13 Thread Alex Deucher
On Thu, Oct 9, 2014 at 2:02 AM, Michel D?nzer  wrote:
> From: Michel D?nzer 
>
> The radeon driver uses placement range restrictions for several reasons,
> in particular to make sure BOs in VRAM can be accessed by the CPU, e.g.
> during a page fault.
>
> Without this change, TTM could evict other BOs while trying to satisfy
> the requested placement, even if the evicted BOs were outside of the
> requested placement range. Doing so didn't free up any space in the
> requested placement range, so the (potentially high) eviction cost was
> incurred for no benefit.
>
> Nominating for stable because radeon driver changes in 3.17 made this
> much more noticeable than before.
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=84662
> Cc: stable at vger.kernel.org
> Signed-off-by: Michel D?nzer 

Reviewed-by: Alex Deucher 

Thomas, do you want to pull this through the ttm tree or can I take it
through radeon?

Alex

> ---
>  drivers/gpu/drm/ttm/ttm_bo.c | 20 +---
>  1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
> index 8f5cec6..407fa2d 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
> @@ -709,6 +709,7 @@ out:
>
>  static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
> uint32_t mem_type,
> +   const struct ttm_place *place,
> bool interruptible,
> bool no_wait_gpu)
>  {
> @@ -720,8 +721,21 @@ static int ttm_mem_evict_first(struct ttm_bo_device 
> *bdev,
> spin_lock(>lru_lock);
> list_for_each_entry(bo, >lru, lru) {
> ret = __ttm_bo_reserve(bo, false, true, false, NULL);
> -   if (!ret)
> +   if (!ret) {
> +   if (place && (place->fpfn || place->lpfn)) {
> +   /* Don't evict this BO if it's outside of the
> +* requested placement range
> +*/
> +   if (place->fpfn >= (bo->mem.start + 
> bo->mem.size) ||
> +   (place->lpfn && place->lpfn <= 
> bo->mem.start)) {
> +   __ttm_bo_unreserve(bo);
> +   ret = -EBUSY;
> +   continue;
> +   }
> +   }
> +
> break;
> +   }
> }
>
> if (ret) {
> @@ -782,7 +796,7 @@ static int ttm_bo_mem_force_space(struct 
> ttm_buffer_object *bo,
> return ret;
> if (mem->mm_node)
> break;
> -   ret = ttm_mem_evict_first(bdev, mem_type,
> +   ret = ttm_mem_evict_first(bdev, mem_type, place,
>   interruptible, no_wait_gpu);
> if (unlikely(ret != 0))
> return ret;
> @@ -1233,7 +1247,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device 
> *bdev,
> spin_lock(>lru_lock);
> while (!list_empty(>lru)) {
> spin_unlock(>lru_lock);
> -   ret = ttm_mem_evict_first(bdev, mem_type, false, false);
> +   ret = ttm_mem_evict_first(bdev, mem_type, NULL, false, false);
> if (ret) {
> if (allow_errors) {
> return ret;
> --
> 2.1.1
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/ttm: Don't skip fpfn check if lpfn is 0 in ttm_bo_mem_compat

2014-10-13 Thread Alex Deucher
On Thu, Oct 9, 2014 at 5:56 AM, Christian K?nig  
wrote:
> Am 09.10.2014 um 08:03 schrieb Michel D?nzer:
>>
>> From: Michel D?nzer 
>>
>> Signed-off-by: Michel D?nzer 
>
>
> Reviewed-by: Christian K?nig 
>
>

Thomas, do you want to pull this through the ttm tree or can I take it
through radeon?

Alex

>> ---
>>   drivers/gpu/drm/ttm/ttm_bo.c | 8 
>>   1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
>> index 407fa2d..d395b0b 100644
>> --- a/drivers/gpu/drm/ttm/ttm_bo.c
>> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
>> @@ -1008,9 +1008,9 @@ static bool ttm_bo_mem_compat(struct ttm_placement
>> *placement,
>> for (i = 0; i < placement->num_placement; i++) {
>> const struct ttm_place *heap = >placement[i];
>> -   if (mem->mm_node && heap->lpfn != 0 &&
>> +   if (mem->mm_node &&
>> (mem->start < heap->fpfn ||
>> -mem->start + mem->num_pages > heap->lpfn))
>> +(heap->lpfn != 0 && (mem->start + mem->num_pages) >
>> heap->lpfn)))
>> continue;
>> *new_flags = heap->flags;
>> @@ -1021,9 +1021,9 @@ static bool ttm_bo_mem_compat(struct ttm_placement
>> *placement,
>> for (i = 0; i < placement->num_busy_placement; i++) {
>> const struct ttm_place *heap =
>> >busy_placement[i];
>> -   if (mem->mm_node && heap->lpfn != 0 &&
>> +   if (mem->mm_node &&
>> (mem->start < heap->fpfn ||
>> -mem->start + mem->num_pages > heap->lpfn))
>> +(heap->lpfn != 0 && (mem->start + mem->num_pages) >
>> heap->lpfn)))
>> continue;
>> *new_flags = heap->flags;
>
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


r600_dma_ring_test() failed - synchronization problem with write-combining memory

2014-10-13 Thread Alex Deucher
On Fri, Oct 10, 2014 at 12:00 PM, Alex Deucher  wrote:
> On Thu, Oct 9, 2014 at 3:10 PM, Alexander Fyodorov  wrote:
>> 09.10.2014, 22:32, "Christian K?nig" :
>>> Am 09.10.2014 um 20:15 schrieb Alexander Fyodorov:
>>>>  09.10.2014, 21:42, "Christian K?nig" :
>>>>>  For VRAM it is true that we have a couple of different caches between
>>>>>  the CPU and the actually memory, which need to be flushed explicitly if
>>>>>  you want to see a value written by the GPU.
>>>>  Then maybe such a flush is what I need. How do I put it in the 
>>>> instruction ring buffer?
>>>
>>> At least we need to flush the HDP, but what hardware generation is this
>>> exactly? Some R6xx don't support hardware flushes in the ring buffer.
>>
>> I observed the problem on HD2400 and HD6670.
>>
>>> Try to call r600_mmio_hdp_flush(rdev) from the loop which checks the
>>> value written.
>>
>> Yep, it helped. Here is the patch against 3.10.53, tested on HD2400.
>>
>>
>> Flush VRAM cache before each read when polling.
>>
>> Signed-off-by: Alexander Fyodorov 
>>
>>
>> Index: drivers/gpu/drm/radeon/r600.c
>> ===
>> --- drivers/gpu/drm/radeon/r600.c   (revision 11647)
>> +++ drivers/gpu/drm/radeon/r600.c   (working copy)
>> @@ -2899,6 +2899,7 @@
>> radeon_ring_unlock_commit(rdev, ring);
>>
>> for (i = 0; i < rdev->usec_timeout; i++) {
>> +   r600_ioctl_wait_idle(rdev, rdev->vram_scratch.robj);
>> tmp = readl(ptr);
>> if (tmp == 0xDEADBEEF)
>> break;
>
> I think I'd prefer to just switch the test to use gart memory since
> this code is shared by different asics thay may not all implement hdp
> flush the same way.  We can just reserve a couple of slots in the wb
> page.

Does the attached patch work for you as well?

Alex
-- next part --
A non-text attachment was scrubbed...
Name: 0001-drm-radeon-use-gart-memory-for-DMA-ring-tests.patch
Type: text/x-patch
Size: 4168 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/d7927386/attachment.bin>


[PATCH] drm/nouveau/disp: Use NULL for pointers

2014-10-13 Thread Thierry Reding
On Mon, Jul 21, 2014 at 02:02:58PM +0200, Thierry Reding wrote:
> From: Thierry Reding 
> 
> The return type of exec_lookup() is struct nvkm_output *, so it should
> return NULL rather than 0.
> 
> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c 
> b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
> index fa30d8196f35..ebf64e1d0a70 100644
> --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
> +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
> @@ -939,7 +939,7 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int 
> or, u32 ctrl,
>   case 0x0900: type = DCB_OUTPUT_DP; mask = 2; break;
>   default:
>   nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
> - return 0x;
> + return NULL;
>   }
>   }
>  

Ping?

Thierry
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/b8e73bbb/attachment.sig>


[PATCH RESEND] regulator: Add stub for devm_regulator_get_exclusive

2014-10-13 Thread Mark Brown
On Thu, Oct 09, 2014 at 07:14:18PM +0800, Axel Lin wrote:
> Also makes regulator_get_exclusive and devm_regulator_get_exclusive stub
> functions return error pointer.
> 
> Signed-off-by: Axel Lin 
> ---
> Hi Mark,
> I hit below build error and then found this patch is still not yet upstream.
> So here is a resend.
> 
>   CC [M]  drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.o
> drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c: In function 'mdp4_kms_init':
> drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c:384:2: error: implicit declaration of 
> function 'devm_regulator_get_exclusive' 
> [-Werror=implicit-function-declaration]
> drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c:384:16: error: assignment makes 
> pointer from integer without a cast [-Werror]

To be honest the fact that you're hitting bugs with this is kind of
making me think that this is a good idea.  

Looking at the code in the driver there are rather a lot of problems -
the whole way the errors are ignored in the probe function is concerning
and most likely buggy at least with deferred probe. For the immediate
problem with using regulator_get_exclusive() I can't understand why it's
being used at all.  In general all the regulator usage in the driver is
atypical and doesn't look idiomatic - do we understand what's going on
here?
-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/186fcd26/attachment.sig>


[PATCH 11/11] drm/radeon: update the VM after setting BO address

2014-10-13 Thread Christian König
From: Christian K?nig 

This way the necessary VM update is kicked off immediately
if all BOs involved are in GPU accessible memory.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_gem.c | 60 +
 1 file changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index f752c7f..0002575 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -518,6 +518,63 @@ out:
return r;
 }

+/**
+ * radeon_gem_va_update_vm -update the bo_va in its VM
+ *
+ * @rdev: radeon_device pointer
+ * @bo_va: bo_va to update
+ *
+ * Update the bo_va directly after setting it's address. Errors are not
+ * vital here, so they are not reported back to userspace.
+ */
+static void radeon_gem_va_update_vm(struct radeon_device *rdev,
+   struct radeon_bo_va *bo_va)
+{
+   struct ttm_validate_buffer tv, *entry;
+   struct radeon_cs_reloc *vm_bos;
+   struct ww_acquire_ctx ticket;
+   struct list_head list;
+   unsigned domain;
+   int r;
+
+   INIT_LIST_HEAD();
+
+   tv.bo = _va->bo->tbo;
+   tv.shared = true;
+   list_add(, );
+
+   vm_bos = radeon_vm_get_bos(rdev, bo_va->vm, );
+   if (!vm_bos)
+   return;
+
+   r = ttm_eu_reserve_buffers(, , true);
+   if (r)
+   goto error_free;
+
+   list_for_each_entry(entry, , head) {
+   domain = radeon_mem_type_to_domain(entry->bo->mem.mem_type);
+   /* if anything is swapped out don't swap it in here,
+  just abort and wait for the next CS */
+   if (domain == RADEON_GEM_DOMAIN_CPU)
+   goto error_unreserve;
+   }
+
+   r = radeon_vm_clear_freed(rdev, bo_va->vm);
+   if (r)
+   goto error_unreserve;
+
+   r = radeon_vm_bo_update(rdev, bo_va, _va->bo->tbo.mem);
+
+error_unreserve:
+   ttm_eu_backoff_reservation(, );
+
+error_free:
+   kfree(vm_bos);
+
+   if (r)
+   DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
+}
+
 int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
  struct drm_file *filp)
 {
@@ -605,6 +662,9 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
goto out;
}
r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, 
args->flags);
+   if (!r)
+   radeon_gem_va_update_vm(rdev, bo_va);
+
break;
case RADEON_VA_UNMAP:
r = radeon_vm_bo_set_addr(rdev, bo_va, 0, 0);
-- 
1.9.1



[PATCH 10/11] drm/radeon: sync PT updates as shared if they are validating

2014-10-13 Thread Christian König
From: Christian K?nig 

Only invalidating PTEs needs to be executed synchronized to using the PT.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_vm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index 05e6cde..5224b10 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -820,7 +820,8 @@ static void radeon_vm_update_ptes(struct radeon_device 
*rdev,
unsigned nptes;
uint64_t pte;

-   radeon_sync_resv(rdev, >sync, pt->tbo.resv, false);
+   radeon_sync_resv(rdev, >sync, pt->tbo.resv,
+!!(flags & R600_PTE_VALID));

if ((addr & ~mask) == (end & ~mask))
nptes = end - addr;
-- 
1.9.1



[PATCH 09/11] drm/radeon: sync PD updates as shared

2014-10-13 Thread Christian König
From: Christian K?nig 

We never invalidate PD entries and making them valid can
run with other users in parallel.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_vm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index c547fe1..05e6cde 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -695,7 +695,7 @@ int radeon_vm_update_page_directory(struct radeon_device 
*rdev,
if (ib.length_dw != 0) {
radeon_asic_vm_pad_ib(rdev, );

-   radeon_sync_resv(rdev, , pd->tbo.resv, false);
+   radeon_sync_resv(rdev, , pd->tbo.resv, true);
WARN_ON(ib.length_dw > ndw);
r = radeon_ib_schedule(rdev, , NULL, false);
if (r) {
-- 
1.9.1



[PATCH 08/11] drm/radeon: fence BO_VAs manually

2014-10-13 Thread Christian König
From: Christian K?nig 

This allows us to finally remove the VM fence and
so allow concurrent use of it from different engines.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h|  7 +++
 drivers/gpu/drm/radeon/radeon_cs.c |  6 +-
 drivers/gpu/drm/radeon/radeon_vm.c | 17 ++---
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 2813a60..391a312 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -455,6 +455,7 @@ struct radeon_bo_va {
struct list_headbo_list;
uint32_tflags;
uint64_taddr;
+   struct radeon_fence *last_pt_update;
unsignedref_count;

/* protected by vm mutex */
@@ -910,6 +911,8 @@ struct radeon_vm_id {
 };

 struct radeon_vm {
+   struct mutexmutex;
+
struct rb_root  va;

/* BOs moved, but not yet updated in the PT */
@@ -927,10 +930,6 @@ struct radeon_vm {

struct radeon_bo_va *ib_bo_va;

-   struct mutexmutex;
-   /* last fence for cs using this vm */
-   struct radeon_fence *fence;
-
/* for id and flush management per ring */
struct radeon_vm_id ids[RADEON_NUM_RINGS];
 };
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c 
b/drivers/gpu/drm/radeon/radeon_cs.c
index c57a17e..626f7b9 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -505,6 +505,9 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser 
*p,
if (r)
return r;

+   radeon_sync_resv(p->rdev, >ib.sync, vm->page_directory->tbo.resv,
+true);
+
r = radeon_vm_clear_freed(rdev, vm);
if (r)
return r;
@@ -536,6 +539,8 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser 
*p,
r = radeon_vm_bo_update(rdev, bo_va, >tbo.mem);
if (r)
return r;
+
+   radeon_sync_fence(>ib.sync, bo_va->last_pt_update);
}

return radeon_vm_clear_invalids(rdev, vm);
@@ -580,7 +585,6 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
DRM_ERROR("Failed to sync rings: %i\n", r);
goto out;
}
-   radeon_sync_fence(>ib.sync, vm->fence);

if ((rdev->family >= CHIP_TAHITI) &&
(parser->chunk_const_ib_idx != -1)) {
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index 3ca932d..c547fe1 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -275,9 +275,6 @@ void radeon_vm_fence(struct radeon_device *rdev,
 {
unsigned vm_id = vm->ids[fence->ring].id;

-   radeon_fence_unref(>fence);
-   vm->fence = radeon_fence_ref(fence);
-
radeon_fence_unref(>vm_manager.active[vm_id]);
rdev->vm_manager.active[vm_id] = radeon_fence_ref(fence);

@@ -707,8 +704,6 @@ int radeon_vm_update_page_directory(struct radeon_device 
*rdev,
}
ib.fence->is_vm_update = true;
radeon_bo_fence(pd, ib.fence, false);
-   radeon_fence_unref(>fence);
-   vm->fence = radeon_fence_ref(ib.fence);
}
radeon_ib_free(rdev, );

@@ -999,8 +994,8 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
}
ib.fence->is_vm_update = true;
radeon_vm_fence_pts(vm, bo_va->it.start, bo_va->it.last + 1, ib.fence);
-   radeon_fence_unref(>fence);
-   vm->fence = radeon_fence_ref(ib.fence);
+   radeon_fence_unref(_va->last_pt_update);
+   bo_va->last_pt_update = radeon_fence_ref(ib.fence);
radeon_ib_free(rdev, );

return 0;
@@ -1026,6 +1021,7 @@ int radeon_vm_clear_freed(struct radeon_device *rdev,
list_for_each_entry_safe(bo_va, tmp, >freed, vm_status) {
r = radeon_vm_bo_update(rdev, bo_va, NULL);
radeon_bo_unref(_va->bo);
+   radeon_fence_unref(_va->last_pt_update);
kfree(bo_va);
if (r)
return r;
@@ -1084,6 +1080,7 @@ void radeon_vm_bo_rmv(struct radeon_device *rdev,
bo_va->bo = radeon_bo_ref(bo_va->bo);
list_add(_va->vm_status, >freed);
} else {
+   radeon_fence_unref(_va->last_pt_update);
kfree(bo_va);
}

@@ -1130,8 +1127,6 @@ int radeon_vm_init(struct radeon_device *rdev, struct 
radeon_vm *vm)
int i, r;

vm->ib_bo_va = NULL;
-   vm->fence = NULL;
-
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
vm->ids[i].id = 0;
vm->ids[i].flushed_updates = NULL;
@@ -1192,11 +1187,13 @@ void radeon_vm_fini(struct radeon_device *rdev, struct 

[PATCH 07/11] drm/radeon: use one VMID for each ring

2014-10-13 Thread Christian König
From: Christian K?nig 

Use multiple VMIDs for each VM, one for each ring. That allows
us to execute flushes separately on each ring, still not ideal
cause in a lot of cases rings can share IDs.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/cik.c   |  4 +--
 drivers/gpu/drm/radeon/cik_sdma.c  |  2 +-
 drivers/gpu/drm/radeon/ni.c|  6 ++--
 drivers/gpu/drm/radeon/ni_dma.c|  3 +-
 drivers/gpu/drm/radeon/radeon.h| 36 +--
 drivers/gpu/drm/radeon/radeon_vm.c | 59 +++---
 drivers/gpu/drm/radeon/si.c|  6 ++--
 7 files changed, 68 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 203e895..1dc4e4d 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -4042,6 +4042,7 @@ struct radeon_fence *cik_copy_cpdma(struct radeon_device 
*rdev,
 void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
struct radeon_ring *ring = >ring[ib->ring];
+   unsigned vm_id = ib->vm ? ib->vm->ids[ib->ring].id : 0;
u32 header, control = INDIRECT_BUFFER_VALID;

if (ib->is_const_ib) {
@@ -4070,8 +4071,7 @@ void cik_ring_ib_execute(struct radeon_device *rdev, 
struct radeon_ib *ib)
header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
}

-   control |= ib->length_dw |
-   (ib->vm ? (ib->vm->id << 24) : 0);
+   control |= ib->length_dw | (vm_id << 24);

radeon_ring_write(ring, header);
radeon_ring_write(ring,
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c 
b/drivers/gpu/drm/radeon/cik_sdma.c
index 1216a3c..4ebcd47 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -134,7 +134,7 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev,
  struct radeon_ib *ib)
 {
struct radeon_ring *ring = >ring[ib->ring];
-   u32 extra_bits = (ib->vm ? ib->vm->id : 0) & 0xf;
+   u32 extra_bits = (ib->vm ? ib->vm->ids[ib->ring].id : 0) & 0xf;

if (rdev->wb.enabled) {
u32 next_rptr = ring->wptr + 5;
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index bee432d..360de9f 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1373,6 +1373,7 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
struct radeon_ring *ring = >ring[ib->ring];
+   unsigned vm_id = ib->vm ? ib->vm->ids[ib->ring].id : 0;
u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
PACKET3_SH_ACTION_ENA;

@@ -1395,15 +1396,14 @@ void cayman_ring_ib_execute(struct radeon_device *rdev, 
struct radeon_ib *ib)
 #endif
  (ib->gpu_addr & 0xFFFC));
radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF);
-   radeon_ring_write(ring, ib->length_dw | 
- (ib->vm ? (ib->vm->id << 24) : 0));
+   radeon_ring_write(ring, ib->length_dw | (vm_id << 24));

/* flush read cache over gart for this vmid */
radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
radeon_ring_write(ring, 0x);
radeon_ring_write(ring, 0);
-   radeon_ring_write(ring, ((ib->vm ? ib->vm->id : 0) << 24) | 10); /* 
poll interval */
+   radeon_ring_write(ring, (vm_id << 24) | 10); /* poll interval */
 }

 static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
index 1d15f6b..efe98b1 100644
--- a/drivers/gpu/drm/radeon/ni_dma.c
+++ b/drivers/gpu/drm/radeon/ni_dma.c
@@ -123,6 +123,7 @@ void cayman_dma_ring_ib_execute(struct radeon_device *rdev,
struct radeon_ib *ib)
 {
struct radeon_ring *ring = >ring[ib->ring];
+   unsigned vm_id = ib->vm ? ib->vm->ids[ib->ring].id : 0;

if (rdev->wb.enabled) {
u32 next_rptr = ring->wptr + 4;
@@ -140,7 +141,7 @@ void cayman_dma_ring_ib_execute(struct radeon_device *rdev,
 */
while ((ring->wptr & 7) != 5)
radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
-   radeon_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, 
ib->vm ? ib->vm->id : 0, 0));
+   radeon_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, 
vm_id, 0));
radeon_ring_write(ring, (ib->gpu_addr & 0xFFE0));
radeon_ring_write(ring, (ib->length_dw << 12) | 
(upper_32_bits(ib->gpu_addr) & 0xFF));

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c2873d4..2813a60 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -900,33 +900,39 @@ struct radeon_vm_pt {

[PATCH 06/11] drm/radeon: track VM update fences separately

2014-10-13 Thread Christian König
From: Christian K?nig 

Note for each fence if it's a VM page table update or not. This allows
us to determine the last VM update in a sync object and so to figure
out if we need to flush the TLB or not.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon.h   | 18 ++
 drivers/gpu/drm/radeon/radeon_fence.c |  1 +
 drivers/gpu/drm/radeon/radeon_ib.c|  3 ++-
 drivers/gpu/drm/radeon/radeon_sync.c  |  7 +++
 drivers/gpu/drm/radeon/radeon_vm.c| 25 +
 5 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 7c975aa..c2873d4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -359,14 +359,15 @@ struct radeon_fence_driver {
 };

 struct radeon_fence {
-   struct fence base;
+   struct fencebase;

-   struct radeon_device*rdev;
-   uint64_tseq;
+   struct radeon_device*rdev;
+   uint64_tseq;
/* RB, DMA, etc. */
-   unsignedring;
+   unsignedring;
+   boolis_vm_update;

-   wait_queue_tfence_wake;
+   wait_queue_tfence_wake;
 };

 int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring);
@@ -593,6 +594,7 @@ void radeon_semaphore_free(struct radeon_device *rdev,
 struct radeon_sync {
struct radeon_semaphore *semaphores[RADEON_NUM_SYNCS];
struct radeon_fence *sync_to[RADEON_NUM_RINGS];
+   struct radeon_fence *last_vm_update;
 };

 void radeon_sync_create(struct radeon_sync *sync);
@@ -921,8 +923,8 @@ struct radeon_vm {
struct mutexmutex;
/* last fence for cs using this vm */
struct radeon_fence *fence;
-   /* last flush or NULL if we still need to flush */
-   struct radeon_fence *last_flush;
+   /* last flushed PD/PT update */
+   struct radeon_fence *flushed_updates;
/* last use of vmid */
struct radeon_fence *last_id_use;
 };
@@ -2953,7 +2955,7 @@ struct radeon_fence *radeon_vm_grab_id(struct 
radeon_device *rdev,
   struct radeon_vm *vm, int ring);
 void radeon_vm_flush(struct radeon_device *rdev,
  struct radeon_vm *vm,
- int ring);
+int ring, struct radeon_fence *fence);
 void radeon_vm_fence(struct radeon_device *rdev,
 struct radeon_vm *vm,
 struct radeon_fence *fence);
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c 
b/drivers/gpu/drm/radeon/radeon_fence.c
index 9951670..d13d1b5 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -140,6 +140,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
(*fence)->rdev = rdev;
(*fence)->seq = seq;
(*fence)->ring = ring;
+   (*fence)->is_vm_update = false;
fence_init(&(*fence)->base, _fence_ops,
   >fence_queue.lock, rdev->fence_context + ring, seq);
radeon_fence_ring_emit(rdev, ring, *fence);
diff --git a/drivers/gpu/drm/radeon/radeon_ib.c 
b/drivers/gpu/drm/radeon/radeon_ib.c
index 56a1704..c39ce1f 100644
--- a/drivers/gpu/drm/radeon/radeon_ib.c
+++ b/drivers/gpu/drm/radeon/radeon_ib.c
@@ -154,7 +154,8 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct 
radeon_ib *ib,
}

if (ib->vm)
-   radeon_vm_flush(rdev, ib->vm, ib->ring);
+   radeon_vm_flush(rdev, ib->vm, ib->ring,
+   ib->sync.last_vm_update);

if (const_ib) {
radeon_ring_ib_execute(rdev, const_ib->ring, const_ib);
diff --git a/drivers/gpu/drm/radeon/radeon_sync.c 
b/drivers/gpu/drm/radeon/radeon_sync.c
index ddd88fb..02ac8a1 100644
--- a/drivers/gpu/drm/radeon/radeon_sync.c
+++ b/drivers/gpu/drm/radeon/radeon_sync.c
@@ -48,6 +48,8 @@ void radeon_sync_create(struct radeon_sync *sync)

for (i = 0; i < RADEON_NUM_RINGS; ++i)
sync->sync_to[i] = NULL;
+
+   sync->last_vm_update = NULL;
 }

 /**
@@ -68,6 +70,11 @@ void radeon_sync_fence(struct radeon_sync *sync,

other = sync->sync_to[fence->ring];
sync->sync_to[fence->ring] = radeon_fence_later(fence, other);
+
+   if (fence->is_vm_update) {
+   other = sync->last_vm_update;
+   sync->last_vm_update = radeon_fence_later(fence, other);
+   }
 }

 /**
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index 26986be..86336e8 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -190,7 +190,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device 
*rdev,
return NULL;


[PATCH 05/11] drm/radeon: fence PT updates manually v2

2014-10-13 Thread Christian König
From: Christian K?nig 

This allows us to add the real execution fence as shared.

v2: fix typo

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_object.c | 19 ++
 drivers/gpu/drm/radeon/radeon_object.h |  2 ++
 drivers/gpu/drm/radeon/radeon_vm.c | 65 +-
 3 files changed, 62 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_object.c 
b/drivers/gpu/drm/radeon/radeon_object.c
index 99a960a..04980d8 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -792,3 +792,22 @@ int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, 
bool no_wait)
ttm_bo_unreserve(>tbo);
return r;
 }
+
+/**
+ * radeon_bo_fence - add fence to buffer object
+ *
+ * @bo: buffer object in question
+ * @fence: fence to add
+ * @shared: true if fence should be added shared
+ *
+ */
+void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence,
+ bool shared)
+{
+   struct reservation_object *resv = bo->tbo.resv;
+
+   if (shared)
+   reservation_object_add_shared_fence(resv, >base);
+   else
+   reservation_object_add_excl_fence(resv, >base);
+}
diff --git a/drivers/gpu/drm/radeon/radeon_object.h 
b/drivers/gpu/drm/radeon/radeon_object.h
index 1b8ec79..3b0b377 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -155,6 +155,8 @@ extern void radeon_bo_move_notify(struct ttm_buffer_object 
*bo,
  struct ttm_mem_reg *new_mem);
 extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
 extern int radeon_bo_get_surface_reg(struct radeon_bo *bo);
+extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence,
+   bool shared);

 /*
  * sub allocation
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index bf4d41db..26986be 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -143,7 +143,7 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct 
radeon_device *rdev,
list[0].prefered_domains = RADEON_GEM_DOMAIN_VRAM;
list[0].allowed_domains = RADEON_GEM_DOMAIN_VRAM;
list[0].tv.bo = >page_directory->tbo;
-   list[0].tv.shared = false;
+   list[0].tv.shared = true;
list[0].tiling_flags = 0;
list[0].handle = 0;
list_add([0].tv.head, head);
@@ -157,7 +157,7 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct 
radeon_device *rdev,
list[idx].prefered_domains = RADEON_GEM_DOMAIN_VRAM;
list[idx].allowed_domains = RADEON_GEM_DOMAIN_VRAM;
list[idx].tv.bo = [idx].robj->tbo;
-   list[idx].tv.shared = false;
+   list[idx].tv.shared = true;
list[idx].tiling_flags = 0;
list[idx].handle = 0;
list_add([idx++].tv.head, head);
@@ -388,35 +388,25 @@ static void radeon_vm_set_pages(struct radeon_device 
*rdev,
 static int radeon_vm_clear_bo(struct radeon_device *rdev,
  struct radeon_bo *bo)
 {
-struct ttm_validate_buffer tv;
-struct ww_acquire_ctx ticket;
-struct list_head head;
struct radeon_ib ib;
unsigned entries;
uint64_t addr;
int r;

-memset(, 0, sizeof(tv));
-tv.bo = >tbo;
-   tv.shared = false;
-
-INIT_LIST_HEAD();
-list_add(, );
-
-r = ttm_eu_reserve_buffers(, , true);
-if (r)
+   r = radeon_bo_reserve(bo, false);
+   if (r)
return r;

-r = ttm_bo_validate(>tbo, >placement, true, false);
-if (r)
-goto error;
+   r = ttm_bo_validate(>tbo, >placement, true, false);
+   if (r)
+   goto error_unreserve;

addr = radeon_bo_gpu_offset(bo);
entries = radeon_bo_size(bo) / 8;

r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, , NULL, 256);
if (r)
-goto error;
+   goto error_unreserve;

ib.length_dw = 0;

@@ -426,15 +416,15 @@ static int radeon_vm_clear_bo(struct radeon_device *rdev,

r = radeon_ib_schedule(rdev, , NULL, false);
if (r)
-goto error;
+   goto error_free;

-   ttm_eu_fence_buffer_objects(, , >base);
-   radeon_ib_free(rdev, );
+   radeon_bo_fence(bo, ib.fence, false);

-   return 0;
+error_free:
+   radeon_ib_free(rdev, );

-error:
-   ttm_eu_backoff_reservation(, );
+error_unreserve:
+   radeon_bo_unreserve(bo);
return r;
 }

@@ -707,6 +697,7 @@ int radeon_vm_update_page_directory(struct radeon_device 
*rdev,
radeon_ib_free(rdev, );
return r;
}
+   radeon_bo_fence(pd, ib.fence, false);

[PATCH 04/11] drm/radeon: split semaphore and sync object handling v2

2014-10-13 Thread Christian König
From: Christian K?nig 

Previously we just allocated space for four hardware semaphores
in each software semaphore object. Make software semaphore objects
represent only one hardware semaphore address again by splitting
the sync code into it's own object.

v2: fix typo in comment

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/Makefile   |   3 +-
 drivers/gpu/drm/radeon/cik.c  |  18 +--
 drivers/gpu/drm/radeon/cik_sdma.c |  18 +--
 drivers/gpu/drm/radeon/evergreen_dma.c|  18 +--
 drivers/gpu/drm/radeon/r600.c |  18 +--
 drivers/gpu/drm/radeon/r600_dma.c |  18 +--
 drivers/gpu/drm/radeon/radeon.h   |  42 +++---
 drivers/gpu/drm/radeon/radeon_cs.c|   8 +-
 drivers/gpu/drm/radeon/radeon_ib.c|  13 +-
 drivers/gpu/drm/radeon/radeon_semaphore.c | 154 +
 drivers/gpu/drm/radeon/radeon_sync.c  | 213 ++
 drivers/gpu/drm/radeon/radeon_vm.c|   4 +-
 drivers/gpu/drm/radeon/rv770_dma.c|  18 +--
 drivers/gpu/drm/radeon/si_dma.c   |  18 +--
 14 files changed, 303 insertions(+), 260 deletions(-)
 create mode 100644 drivers/gpu/drm/radeon/radeon_sync.c

diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index d01b879..a02434a 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -80,7 +80,8 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
r600_dpm.o rs780_dpm.o rv6xx_dpm.o rv770_dpm.o rv730_dpm.o rv740_dpm.o \
rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o 
\
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
-   ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o
+   ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o radeon_mn.o 
\
+   radeon_sync.o

 # add async DMA block
 radeon-y += \
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 5e58504..203e895 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -3970,31 +3970,27 @@ struct radeon_fence *cik_copy_cpdma(struct 
radeon_device *rdev,
unsigned num_gpu_pages,
struct reservation_object *resv)
 {
-   struct radeon_semaphore *sem = NULL;
struct radeon_fence *fence;
+   struct radeon_sync sync;
int ring_index = rdev->asic->copy.blit_ring_index;
struct radeon_ring *ring = >ring[ring_index];
u32 size_in_bytes, cur_size_in_bytes, control;
int i, num_loops;
int r = 0;

-   r = radeon_semaphore_create(rdev, );
-   if (r) {
-   DRM_ERROR("radeon: moving bo (%d).\n", r);
-   return ERR_PTR(r);
-   }
+   radeon_sync_create();

size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT);
num_loops = DIV_ROUND_UP(size_in_bytes, 0x1f);
r = radeon_ring_lock(rdev, ring, num_loops * 7 + 18);
if (r) {
DRM_ERROR("radeon: moving bo (%d).\n", r);
-   radeon_semaphore_free(rdev, , NULL);
+   radeon_sync_free(rdev, , NULL);
return ERR_PTR(r);
}

-   radeon_semaphore_sync_resv(rdev, sem, resv, false);
-   radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+   radeon_sync_resv(rdev, , resv, false);
+   radeon_sync_rings(rdev, , ring->idx);

for (i = 0; i < num_loops; i++) {
cur_size_in_bytes = size_in_bytes;
@@ -4018,12 +4014,12 @@ struct radeon_fence *cik_copy_cpdma(struct 
radeon_device *rdev,
r = radeon_fence_emit(rdev, , ring->idx);
if (r) {
radeon_ring_unlock_undo(rdev, ring);
-   radeon_semaphore_free(rdev, , NULL);
+   radeon_sync_free(rdev, , NULL);
return ERR_PTR(r);
}

radeon_ring_unlock_commit(rdev, ring, false);
-   radeon_semaphore_free(rdev, , fence);
+   radeon_sync_free(rdev, , fence);

return fence;
 }
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c 
b/drivers/gpu/drm/radeon/cik_sdma.c
index 2bc8a2f..1216a3c 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -548,31 +548,27 @@ struct radeon_fence *cik_copy_dma(struct radeon_device 
*rdev,
  unsigned num_gpu_pages,
  struct reservation_object *resv)
 {
-   struct radeon_semaphore *sem = NULL;
struct radeon_fence *fence;
+   struct radeon_sync sync;
int ring_index = rdev->asic->copy.dma_ring_index;
struct radeon_ring *ring = >ring[ring_index];
u32 size_in_bytes, cur_size_in_bytes;
int i, num_loops;
int r = 0;

-   r = radeon_semaphore_create(rdev, );
-   if (r) {
-   DRM_ERROR("radeon: moving bo (%d).\n", r);
-   return 

[PATCH 03/11] drm/radeon: remove unnecessary VM syncs

2014-10-13 Thread Christian König
From: Christian K?nig 

The PD/PTs reservation object now contains everything needed.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_vm.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index 9c9aa62..df1a768 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -701,7 +701,6 @@ int radeon_vm_update_page_directory(struct radeon_device 
*rdev,
radeon_asic_vm_pad_ib(rdev, );

radeon_semaphore_sync_resv(rdev, ib.semaphore, pd->tbo.resv, 
false);
-   radeon_semaphore_sync_fence(ib.semaphore, vm->last_id_use);
WARN_ON(ib.length_dw > ndw);
r = radeon_ib_schedule(rdev, , NULL, false);
if (r) {
@@ -969,7 +968,6 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
radeon_asic_vm_pad_ib(rdev, );
WARN_ON(ib.length_dw > ndw);

-   radeon_semaphore_sync_fence(ib.semaphore, vm->fence);
r = radeon_ib_schedule(rdev, , NULL, false);
if (r) {
radeon_ib_free(rdev, );
-- 
1.9.1



[PATCH 02/11] drm/radeon: stop re-reserving the BO in radeon_vm_bo_set_addr

2014-10-13 Thread Christian König
From: Christian K?nig 

That's useless when all callers drop the reservation
immediately after calling the function.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/radeon_gem.c | 2 +-
 drivers/gpu/drm/radeon/radeon_kms.c | 2 --
 drivers/gpu/drm/radeon/radeon_vm.c  | 4 ++--
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_gem.c 
b/drivers/gpu/drm/radeon/radeon_gem.c
index c194497..f752c7f 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -601,6 +601,7 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
if (bo_va->it.start) {
args->operation = RADEON_VA_RESULT_VA_EXIST;
args->offset = bo_va->it.start * RADEON_GPU_PAGE_SIZE;
+   radeon_bo_unreserve(rbo);
goto out;
}
r = radeon_vm_bo_set_addr(rdev, bo_va, args->offset, 
args->flags);
@@ -616,7 +617,6 @@ int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
args->operation = RADEON_VA_RESULT_ERROR;
}
 out:
-   radeon_bo_unreserve(rbo);
drm_gem_object_unreference_unlocked(gobj);
return r;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c 
b/drivers/gpu/drm/radeon/radeon_kms.c
index 8309b11..85ee6f7 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -621,8 +621,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
  RADEON_VA_IB_OFFSET,
  RADEON_VM_PAGE_READABLE |
  RADEON_VM_PAGE_SNOOPED);
-
-   radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
if (r) {
radeon_vm_fini(rdev, vm);
kfree(fpriv);
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c 
b/drivers/gpu/drm/radeon/radeon_vm.c
index 45987a4..9c9aa62 100644
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -450,7 +450,7 @@ error:
  * Validate and set the offset requested within the vm address space.
  * Returns 0 for success, error for failure.
  *
- * Object has to be reserved!
+ * Object has to be reserved and gets unreserved by this function!
  */
 int radeon_vm_bo_set_addr(struct radeon_device *rdev,
  struct radeon_bo_va *bo_va,
@@ -576,7 +576,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
}

mutex_unlock(>mutex);
-   return radeon_bo_reserve(bo_va->bo, false);
+   return 0;
 }

 /**
-- 
1.9.1



[PATCH 01/11] drm/radeon: rework vm_flush parameters

2014-10-13 Thread Christian König
From: Christian K?nig 

Use ring structure instead of index and provide vm_id and pd_addr separately.

Signed-off-by: Christian K?nig 
---
 drivers/gpu/drm/radeon/cik.c | 23 ++-
 drivers/gpu/drm/radeon/cik_sdma.c| 22 +-
 drivers/gpu/drm/radeon/ni.c  | 14 +-
 drivers/gpu/drm/radeon/ni_dma.c  | 14 +-
 drivers/gpu/drm/radeon/radeon.h  |  5 +++--
 drivers/gpu/drm/radeon/radeon_asic.h | 18 --
 drivers/gpu/drm/radeon/radeon_vm.c   |  3 ++-
 drivers/gpu/drm/radeon/si.c  | 18 +++---
 drivers/gpu/drm/radeon/si_dma.c  | 19 ---
 9 files changed, 61 insertions(+), 75 deletions(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index d48a539..5e58504 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -5958,26 +5958,23 @@ static void cik_vm_decode_fault(struct radeon_device 
*rdev,
  * Update the page table base and flush the VM TLB
  * using the CP (CIK).
  */
-void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
+void cik_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
+ unsigned vm_id, uint64_t pd_addr)
 {
-   struct radeon_ring *ring = >ring[ridx];
-   int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX);
-
-   if (vm == NULL)
-   return;
+   int usepfp = (ring->idx == RADEON_RING_TYPE_GFX_INDEX);

radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
 WRITE_DATA_DST_SEL(0)));
-   if (vm->id < 8) {
+   if (vm_id < 8) {
radeon_ring_write(ring,
- (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id 
<< 2)) >> 2);
+ (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 
2)) >> 2);
} else {
radeon_ring_write(ring,
- (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm->id 
- 8) << 2)) >> 2);
+ (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm_id - 
8) << 2)) >> 2);
}
radeon_ring_write(ring, 0);
-   radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
+   radeon_ring_write(ring, pd_addr >> 12);

/* update SH_MEM_* regs */
radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -5985,7 +5982,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, 
struct radeon_vm *vm)
 WRITE_DATA_DST_SEL(0)));
radeon_ring_write(ring, SRBM_GFX_CNTL >> 2);
radeon_ring_write(ring, 0);
-   radeon_ring_write(ring, VMID(vm->id));
+   radeon_ring_write(ring, VMID(vm_id));

radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 6));
radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -6006,7 +6003,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, 
struct radeon_vm *vm)
radeon_ring_write(ring, VMID(0));

/* HDP flush */
-   cik_hdp_flush_cp_ring_emit(rdev, ridx);
+   cik_hdp_flush_cp_ring_emit(rdev, ring->idx);

/* bits 0-15 are the VM contexts0-15 */
radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -6014,7 +6011,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, 
struct radeon_vm *vm)
 WRITE_DATA_DST_SEL(0)));
radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
radeon_ring_write(ring, 0);
-   radeon_ring_write(ring, 1 << vm->id);
+   radeon_ring_write(ring, 1 << vm_id);

/* compute doesn't have PFP */
if (usepfp) {
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c 
b/drivers/gpu/drm/radeon/cik_sdma.c
index c473c91..2bc8a2f 100644
--- a/drivers/gpu/drm/radeon/cik_sdma.c
+++ b/drivers/gpu/drm/radeon/cik_sdma.c
@@ -905,25 +905,21 @@ void cik_sdma_vm_pad_ib(struct radeon_ib *ib)
  * Update the page table base and flush the VM TLB
  * using sDMA (CIK).
  */
-void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm 
*vm)
+void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
+ unsigned vm_id, uint64_t pd_addr)
 {
-   struct radeon_ring *ring = >ring[ridx];
-
-   if (vm == NULL)
-   return;
-
radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
-   if (vm->id < 8) {
-   radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + 
(vm->id << 2)) >> 2);
+   if (vm_id < 8) {
+   radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + 
(vm_id << 2)) >> 2);
} else {
-   radeon_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + 
((vm->id - 8) << 2)) >> 2);
+   radeon_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + 
((vm_id - 8) << 2)) >> 2);
}
-   

[PATCH 14/14] drm/tegra: dsi: Set up PHY_TIMING & BTA_TIMING registers earlier

2014-10-13 Thread Thierry Reding
From: Sean Paul 

Make sure the DSI PHY_TIMING and BTA_TIMING registers are initialized
when the clocks are set up as opposed to when the output is enabled.
This makes sure that the PHY timings are properly set up when the panel
is prepared and that DCS commands sent at that time use the appropriate
timings.

Signed-off-by: Sean Paul 
---
 drivers/gpu/drm/tegra/dsi.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index b7b205496e8c..0adc7804e261 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -389,6 +389,9 @@ static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi)
DSI_TIMING_FIELD(timing.tago, period, 1);
tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);

+   if (dsi->slave)
+   return tegra_dsi_set_phy_timing(dsi->slave);
+
return 0;
 }

@@ -536,10 +539,6 @@ static int tegra_dsi_configure(struct tegra_dsi *dsi, 
unsigned int pipe,
value &= ~DSI_CONTROL_HOST_ENABLE;
tegra_dsi_writel(dsi, value, DSI_CONTROL);

-   err = tegra_dsi_set_phy_timing(dsi);
-   if (err < 0)
-   return err;
-
for (i = 0; i < NUM_PKT_SEQ; i++)
tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);

@@ -860,6 +859,10 @@ static int tegra_output_dsi_setup_clock(struct 
tegra_output *output,
 */
tegra_dsi_set_timeout(dsi, bclk, vrefresh);

+   err = tegra_dsi_set_phy_timing(dsi);
+   if (err < 0)
+   return err;
+
return 0;
 }

-- 
2.1.2



[PATCH 13/14] drm/tegra: dsi: Add ganged mode support

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Implement ganged mode support for the Tegra DSI driver. The DSI host
controller to gang up with is specified via a phandle in the device tree
and the resolved DSI host controller used for the programming of the
ganged-mode registers.

Signed-off-by: Thierry Reding 
---
 .../bindings/gpu/nvidia,tegra20-host1x.txt |   2 +
 drivers/gpu/drm/tegra/dsi.c| 767 +
 drivers/gpu/drm/tegra/dsi.h|  14 +-
 3 files changed, 666 insertions(+), 117 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt 
b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
index b48f4ef31d93..4c32ef0b7db8 100644
--- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -191,6 +191,8 @@ of the following host1x client modules:
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
+  - nvidia,ganged-mode: contains a phandle to a second DSI controller to gang
+up with in order to support up to 8 data lanes

 - sor: serial output resource

diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 584b771d8b2f..b7b205496e8c 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 

@@ -54,6 +55,10 @@ struct tegra_dsi {

unsigned int video_fifo_depth;
unsigned int host_fifo_depth;
+
+   /* for ganged-mode support */
+   struct tegra_dsi *master;
+   struct tegra_dsi *slave;
 };

 static inline struct tegra_dsi *
@@ -318,6 +323,21 @@ static const u32 
pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
 };

+static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = {
+   [ 0] = 0,
+   [ 1] = 0,
+   [ 2] = 0,
+   [ 3] = 0,
+   [ 4] = 0,
+   [ 5] = 0,
+   [ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP,
+   [ 7] = 0,
+   [ 8] = 0,
+   [ 9] = 0,
+   [10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP,
+   [11] = 0,
+};
+
 static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi)
 {
struct mipi_dphy_timing timing;
@@ -329,7 +349,7 @@ static int tegra_dsi_set_phy_timing(struct tegra_dsi *dsi)
if (rate < 0)
return rate;

-   period = DIV_ROUND_CLOSEST(10UL, rate * 2);
+   period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate * 2);

err = mipi_dphy_timing_get_default(, period);
if (err < 0)
@@ -426,26 +446,59 @@ static int tegra_dsi_get_format(enum 
mipi_dsi_pixel_format format,
return 0;
 }

-static int tegra_output_dsi_enable(struct tegra_output *output)
+static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
+   unsigned int size)
+{
+   u32 value;
+
+   tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
+   tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
+
+   value = DSI_GANGED_MODE_CONTROL_ENABLE;
+   tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
+}
+
+static void tegra_dsi_enable(struct tegra_dsi *dsi)
+{
+   u32 value;
+
+   value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
+   value |= DSI_POWER_CONTROL_ENABLE;
+   tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
+
+   if (dsi->slave)
+   tegra_dsi_enable(dsi->slave);
+}
+
+static unsigned int tegra_dsi_get_lanes(struct tegra_dsi *dsi)
+{
+   if (dsi->master)
+   return dsi->master->lanes + dsi->lanes;
+
+   if (dsi->slave)
+   return dsi->lanes + dsi->slave->lanes;
+
+   return dsi->lanes;
+}
+
+static int tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
+  const struct drm_display_mode *mode)
 {
-   struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
-   struct drm_display_mode *mode = >base.mode;
unsigned int hact, hsw, hbp, hfp, i, mul, div;
-   struct tegra_dsi *dsi = to_dsi(output);
enum tegra_dsi_format format;
-   unsigned long value;
const u32 *pkt_seq;
+   u32 value;
int err;

-   if (dsi->enabled)
-   return 0;
-
if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n");
pkt_seq = pkt_seq_video_non_burst_sync_pulses;
-   } else {
+   } else if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
DRM_DEBUG_KMS("Non-burst video mode with sync events\n");
pkt_seq = pkt_seq_video_non_burst_sync_events;
+   } else {
+   DRM_DEBUG_KMS("Command mode\n");
+   pkt_seq = 

[PATCH 12/14] drm/tegra: dsi: Make FIFO depths host parameters

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Rather than hardcoding them as macros, make the host and video FIFO
depths parameters so that they can be more easily adjusted if a new
generation of the Tegra SoC changes them.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/tegra/dsi.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index f7874458926a..584b771d8b2f 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -26,9 +26,6 @@
 #include "dsi.h"
 #include "mipi-phy.h"

-#define DSI_VIDEO_FIFO_DEPTH (1920 / 4)
-#define DSI_HOST_FIFO_DEPTH 64
-
 struct tegra_dsi {
struct host1x_client client;
struct tegra_output output;
@@ -54,6 +51,9 @@ struct tegra_dsi {

struct regulator *vdd;
bool enabled;
+
+   unsigned int video_fifo_depth;
+   unsigned int host_fifo_depth;
 };

 static inline struct tegra_dsi *
@@ -467,7 +467,7 @@ static int tegra_output_dsi_enable(struct tegra_output 
*output)
DSI_CONTROL_SOURCE(dc->pipe);
tegra_dsi_writel(dsi, value, DSI_CONTROL);

-   tegra_dsi_writel(dsi, DSI_VIDEO_FIFO_DEPTH, DSI_MAX_THRESHOLD);
+   tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD);

value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS |
DSI_HOST_CONTROL_ECC;
@@ -843,6 +843,8 @@ static int tegra_dsi_probe(struct platform_device *pdev)
return -ENOMEM;

dsi->output.dev = dsi->dev = >dev;
+   dsi->video_fifo_depth = 1920;
+   dsi->host_fifo_depth = 64;

err = tegra_output_probe(>output);
if (err < 0)
-- 
2.1.2



[PATCH 11/14] drm/tegra: Do not enable output on .mode_set()

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

The output is already enabled in .dpms(), doing it in .mode_set() too
can cause noticable flicker.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/tegra/output.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 0c67d7eebc94..6b393cfbb5e7 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -167,12 +167,6 @@ static void tegra_encoder_mode_set(struct drm_encoder 
*encoder,
   struct drm_display_mode *mode,
   struct drm_display_mode *adjusted)
 {
-   struct tegra_output *output = encoder_to_output(encoder);
-   int err;
-
-   err = tegra_output_enable(output);
-   if (err < 0)
-   dev_err(encoder->dev->dev, "tegra_output_enable(): %d\n", err);
 }

 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-- 
2.1.2



[PATCH 10/14] drm/tegra: dc: Add powergate support

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Both display controllers are in their own power partition. Currently the
driver relies on the assumption that these partitions are on (which is
the hardware default). However some bootloaders may disable them, so the
driver must make sure to turn them back on to avoid hangs.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/tegra/dc.c  | 45 ++---
 drivers/gpu/drm/tegra/drm.h |  1 +
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 6553fd238685..4a015232e2e8 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,6 +11,8 @@
 #include 
 #include 

+#include 
+
 #include "dc.h"
 #include "drm.h"
 #include "gem.h"
@@ -20,6 +22,7 @@ struct tegra_dc_soc_info {
bool supports_cursor;
bool supports_block_linear;
unsigned int pitch_align;
+   bool has_powergate;
 };

 struct tegra_plane {
@@ -1357,6 +1360,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info 
= {
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 8,
+   .has_powergate = false,
 };

 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -1364,6 +1368,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info 
= {
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 8,
+   .has_powergate = false,
 };

 static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -1371,6 +1376,7 @@ static const struct tegra_dc_soc_info 
tegra114_dc_soc_info = {
.supports_cursor = false,
.supports_block_linear = false,
.pitch_align = 64,
+   .has_powergate = true,
 };

 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -1378,6 +1384,7 @@ static const struct tegra_dc_soc_info 
tegra124_dc_soc_info = {
.supports_cursor = true,
.supports_block_linear = true,
.pitch_align = 64,
+   .has_powergate = true,
 };

 static const struct of_device_id tegra_dc_of_match[] = {
@@ -1385,6 +1392,9 @@ static const struct of_device_id tegra_dc_of_match[] = {
.compatible = "nvidia,tegra124-dc",
.data = _dc_soc_info,
}, {
+   .compatible = "nvidia,tegra114-dc",
+   .data = _dc_soc_info,
+   }, {
.compatible = "nvidia,tegra30-dc",
.data = _dc_soc_info,
}, {
@@ -1467,9 +1477,34 @@ static int tegra_dc_probe(struct platform_device *pdev)
return PTR_ERR(dc->rst);
}

-   err = clk_prepare_enable(dc->clk);
-   if (err < 0)
-   return err;
+   if (dc->soc->has_powergate) {
+   if (dc->pipe == 0)
+   dc->powergate = TEGRA_POWERGATE_DIS;
+   else
+   dc->powergate = TEGRA_POWERGATE_DISB;
+
+   err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
+   dc->rst);
+   if (err < 0) {
+   dev_err(>dev, "failed to power partition: %d\n",
+   err);
+   return err;
+   }
+   } else {
+   err = clk_prepare_enable(dc->clk);
+   if (err < 0) {
+   dev_err(>dev, "failed to enable clock: %d\n",
+   err);
+   return err;
+   }
+
+   err = reset_control_deassert(dc->rst);
+   if (err < 0) {
+   dev_err(>dev, "failed to deassert reset: %d\n",
+   err);
+   return err;
+   }
+   }

regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dc->regs = devm_ioremap_resource(>dev, regs);
@@ -1523,6 +1558,10 @@ static int tegra_dc_remove(struct platform_device *pdev)
}

reset_control_assert(dc->rst);
+
+   if (dc->soc->has_powergate)
+   tegra_powergate_power_off(dc->powergate);
+
clk_disable_unprepare(dc->clk);

return 0;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index e89c70fa82d5..b994c017971d 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -101,6 +101,7 @@ struct tegra_dc {
spinlock_t lock;

struct drm_crtc base;
+   int powergate;
int pipe;

struct clk *clk;
-- 
2.1.2



[PATCH 09/14] gpu: host1x: mipi: Set MIPI_CAL_BIAS_PAD_CFG1 register

2014-10-13 Thread Thierry Reding
From: Sean Paul 

During calibration, sets the "internal reference level for drive pull-
down" to the value specified in the Tegra TRM.

Signed-off-by: Sean Paul 
Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/mipi.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index 22e20c2399c5..fbc6ee6ca337 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -72,6 +72,7 @@
 #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0)

 #define MIPI_CAL_BIAS_PAD_CFG1 0x17
+#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)

 #define MIPI_CAL_BIAS_PAD_CFG2 0x18
 #define MIPI_CAL_BIAS_PAD_PDVREG   (1 << 1)
@@ -203,6 +204,9 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device)
value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);

+   tegra_mipi_writel(device->mipi, MIPI_CAL_BIAS_PAD_DRV_DN_REF(2),
+ MIPI_CAL_BIAS_PAD_CFG1);
+
value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
-- 
2.1.2



[PATCH 08/14] gpu: host1x: mipi: Calibrate clock lanes

2014-10-13 Thread Thierry Reding
From: Sean Paul 

Include the clock lanes when calibrating the MIPI PHY on Tegra124
compatible devices.

Signed-off-by: Sean Paul 
[treding at nvidia.com: bikeshedding]
Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/mipi.c | 124 ++
 1 file changed, 92 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index 0d8c3ae8db6a..22e20c2399c5 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -49,11 +49,24 @@
 #define MIPI_CAL_CONFIG_DSIC   0x10
 #define MIPI_CAL_CONFIG_DSID   0x11

+#define MIPI_CAL_CONFIG_DSIAB_CLK  0x19
+#define MIPI_CAL_CONFIG_DSICD_CLK  0x1a
+#define MIPI_CAL_CONFIG_CSIAB_CLK  0x1b
+#define MIPI_CAL_CONFIG_CSICD_CLK  0x1c
+#define MIPI_CAL_CONFIG_CSIE_CLK   0x1d
+
+/* for data and clock lanes */
 #define MIPI_CAL_CONFIG_SELECT (1 << 21)
+
+/* for data lanes */
 #define MIPI_CAL_CONFIG_HSPDOS(x)  (((x) & 0x1f) << 16)
 #define MIPI_CAL_CONFIG_HSPUOS(x)  (((x) & 0x1f) <<  8)
 #define MIPI_CAL_CONFIG_TERMOS(x)  (((x) & 0x1f) <<  0)

+/* for clock lanes */
+#define MIPI_CAL_CONFIG_HSCLKPDOSD(x)  (((x) & 0x1f) <<  8)
+#define MIPI_CAL_CONFIG_HSCLKPUOSD(x)  (((x) & 0x1f) <<  0)
+
 #define MIPI_CAL_BIAS_PAD_CFG0 0x16
 #define MIPI_CAL_BIAS_PAD_PDVCLAMP (1 << 1)
 #define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0)
@@ -63,21 +76,19 @@
 #define MIPI_CAL_BIAS_PAD_CFG2 0x18
 #define MIPI_CAL_BIAS_PAD_PDVREG   (1 << 1)

-static const struct module {
-   unsigned long reg;
-} modules[] = {
-   { .reg = MIPI_CAL_CONFIG_CSIA },
-   { .reg = MIPI_CAL_CONFIG_CSIB },
-   { .reg = MIPI_CAL_CONFIG_CSIC },
-   { .reg = MIPI_CAL_CONFIG_CSID },
-   { .reg = MIPI_CAL_CONFIG_CSIE },
-   { .reg = MIPI_CAL_CONFIG_DSIA },
-   { .reg = MIPI_CAL_CONFIG_DSIB },
-   { .reg = MIPI_CAL_CONFIG_DSIC },
-   { .reg = MIPI_CAL_CONFIG_DSID },
+struct tegra_mipi_pad {
+   unsigned long data;
+   unsigned long clk;
+};
+
+struct tegra_mipi_soc {
+   bool has_clk_lane;
+   const struct tegra_mipi_pad *pads;
+   unsigned int num_pads;
 };

 struct tegra_mipi {
+   const struct tegra_mipi_soc *soc;
void __iomem *regs;
struct mutex lock;
struct clk *clk;
@@ -117,36 +128,35 @@ struct tegra_mipi_device *tegra_mipi_request(struct 
device *device)

dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
-   of_node_put(args.np);
err = -ENOMEM;
goto out;
}

dev->pdev = of_find_device_by_node(args.np);
if (!dev->pdev) {
-   of_node_put(args.np);
err = -ENODEV;
goto free;
}

-   of_node_put(args.np);
-
dev->mipi = platform_get_drvdata(dev->pdev);
if (!dev->mipi) {
err = -EPROBE_DEFER;
-   goto pdev_put;
+   goto put;
}

+   of_node_put(args.np);
+
dev->pads = args.args[0];
dev->device = device;

return dev;

-pdev_put:
+put:
platform_device_put(dev->pdev);
 free:
kfree(dev);
 out:
+   of_node_put(args.np);
return ERR_PTR(err);
 }
 EXPORT_SYMBOL(tegra_mipi_request);
@@ -177,6 +187,7 @@ static int tegra_mipi_wait(struct tegra_mipi *mipi)

 int tegra_mipi_calibrate(struct tegra_mipi_device *device)
 {
+   const struct tegra_mipi_soc *soc = device->mipi->soc;
unsigned int i;
u32 value;
int err;
@@ -196,16 +207,23 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device)
value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);

-   for (i = 0; i < ARRAY_SIZE(modules); i++) {
-   if (device->pads & BIT(i))
-   value = MIPI_CAL_CONFIG_SELECT |
-   MIPI_CAL_CONFIG_HSPDOS(0) |
-   MIPI_CAL_CONFIG_HSPUOS(4) |
-   MIPI_CAL_CONFIG_TERMOS(5);
-   else
-   value = 0;
+   for (i = 0; i < soc->num_pads; i++) {
+   u32 clk = 0, data = 0;
+
+   if (device->pads & BIT(i)) {
+   data = MIPI_CAL_CONFIG_SELECT |
+  MIPI_CAL_CONFIG_HSPDOS(0) |
+  MIPI_CAL_CONFIG_HSPUOS(4) |
+  MIPI_CAL_CONFIG_TERMOS(5);
+   clk = MIPI_CAL_CONFIG_SELECT |
+ MIPI_CAL_CONFIG_HSCLKPDOSD(0) |
+ MIPI_CAL_CONFIG_HSCLKPUOSD(4);
+   }
+
+   tegra_mipi_writel(device->mipi, data, soc->pads[i].data);

-   tegra_mipi_writel(device->mipi, value, modules[i].reg);
+   if (soc->has_clk_lane)
+   tegra_mipi_writel(device->mipi, clk, 

[PATCH 07/14] gpu: host1x: mipi: Preserve the contents of MIPI_CAL_CTRL

2014-10-13 Thread Thierry Reding
From: Sean Paul 

By paving the CTRL reg value, the current code changes MIPI_CAL_PRESCALE
("Auto-cal calibration step prescale") from 1us to 0.1us (val=0). In the
description for PHY's noise filter (MIPI_CAL_NOISE_FLT), the TRM states
that if the value of the prescale is 0 (or 0.1us), the filter should be
set between 2-5. However, the current code sets it to 0.

For now, let's keep the prescale and filter values as-is, which is most
likely the power-on-reset values of 0x2 and 0xa, respectively.

Signed-off-by: Sean Paul 
Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/mipi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index a3e215a0116f..0d8c3ae8db6a 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -208,7 +208,9 @@ int tegra_mipi_calibrate(struct tegra_mipi_device *device)
tegra_mipi_writel(device->mipi, value, modules[i].reg);
}

-   tegra_mipi_writel(device->mipi, MIPI_CAL_CTRL_START, MIPI_CAL_CTRL);
+   value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
+   value |= MIPI_CAL_CTRL_START;
+   tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);

err = tegra_mipi_wait(device->mipi);

-- 
2.1.2



[PATCH 06/14] gpu: host1x: mipi: Registers are 32 bits wide

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

On 64-bit platforms an unsigned long would be 64 bit and cause
unnecessary casting when being passed to writel() or returned from
readl(). Make register values 32 bits wide to avoid that.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/mipi.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index 9882ea122024..a3e215a0116f 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -90,16 +90,16 @@ struct tegra_mipi_device {
unsigned long pads;
 };

-static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi,
-unsigned long reg)
+static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
+  unsigned long offset)
 {
-   return readl(mipi->regs + (reg << 2));
+   return readl(mipi->regs + (offset << 2));
 }

-static inline void tegra_mipi_writel(struct tegra_mipi *mipi,
-unsigned long value, unsigned long reg)
+static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
+unsigned long offset)
 {
-   writel(value, mipi->regs + (reg << 2));
+   writel(value, mipi->regs + (offset << 2));
 }

 struct tegra_mipi_device *tegra_mipi_request(struct device *device)
@@ -161,7 +161,7 @@ EXPORT_SYMBOL(tegra_mipi_free);
 static int tegra_mipi_wait(struct tegra_mipi *mipi)
 {
unsigned long timeout = jiffies + msecs_to_jiffies(250);
-   unsigned long value;
+   u32 value;

while (time_before(jiffies, timeout)) {
value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
@@ -177,8 +177,8 @@ static int tegra_mipi_wait(struct tegra_mipi *mipi)

 int tegra_mipi_calibrate(struct tegra_mipi_device *device)
 {
-   unsigned long value;
unsigned int i;
+   u32 value;
int err;

err = clk_enable(device->mipi->clk);
-- 
2.1.2



[PATCH 05/14] gpu: host1x: Make gather offsets unsigned

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Use the u32 type for the offset in the host1x_job_gather structure for
consistentcy with other structures. Negative offsets don't make sense in
this context.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/job.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h
index 33a697d6dcef..8b3c15df0660 100644
--- a/drivers/gpu/host1x/job.h
+++ b/drivers/gpu/host1x/job.h
@@ -23,7 +23,7 @@ struct host1x_job_gather {
u32 words;
dma_addr_t base;
struct host1x_bo *bo;
-   int offset;
+   u32 offset;
bool handled;
 };

-- 
2.1.2



[PATCH 04/14] gpu: host1x: Print address/offset pairs consistently

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Consistently use a format of %pad+%#x to print address/offset in debug
messages.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/hw/cdma_hw.c  | 4 ++--
 drivers/gpu/host1x/hw/debug_hw.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c
index 072d8209c06c..305ea8f3382d 100644
--- a/drivers/gpu/host1x/hw/cdma_hw.c
+++ b/drivers/gpu/host1x/hw/cdma_hw.c
@@ -54,8 +54,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, 
u32 getptr,
u32 *p = (u32 *)(pb->mapped + getptr);
*(p++) = HOST1X_OPCODE_NOP;
*(p++) = HOST1X_OPCODE_NOP;
-   dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__,
-   (u64)pb->phys + getptr);
+   dev_dbg(host1x->dev, "%s: NOP at %pad+%#x\n", __func__,
+   >phys, getptr);
getptr = (getptr + 8) & (pb->size_bytes - 1);
}
wmb();
diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c
index f72c873eff81..791de9351eeb 100644
--- a/drivers/gpu/host1x/hw/debug_hw.c
+++ b/drivers/gpu/host1x/hw/debug_hw.c
@@ -163,8 +163,8 @@ static void show_channel_gathers(struct output *o, struct 
host1x_cdma *cdma)
continue;
}

-   host1x_debug_output(o, "GATHER at %#llx+%04x, %d 
words\n",
-   (u64)g->base, g->offset, g->words);
+   host1x_debug_output(o, "GATHER at %pad+%#x, %d 
words\n",
+   >base, g->offset, g->words);

show_gather(o, g->base + g->offset, g->words, cdma,
g->base, mapped);
-- 
2.1.2



[PATCH 03/14] gpu: host1x: Fix typo in comment

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/hw/cdma_hw.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c
index a1197c40a454..072d8209c06c 100644
--- a/drivers/gpu/host1x/hw/cdma_hw.c
+++ b/drivers/gpu/host1x/hw/cdma_hw.c
@@ -26,7 +26,7 @@
 #include "../debug.h"

 /*
- * Put the restart at the end of pushbuffer memor
+ * Put the restart at the end of pushbuffer memory
  */
 static void push_buffer_init(struct push_buffer *pb)
 {
-- 
2.1.2



[PATCH 02/14] gpu: host1x: Make mapped field of push buffers void *

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

This reduces the amount of casting that needs to be done to get rid of
annoying warnings on 64-bit builds.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/cdma.c   | 2 +-
 drivers/gpu/host1x/cdma.h   | 2 +-
 drivers/gpu/host1x/hw/cdma_hw.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/host1x/cdma.c b/drivers/gpu/host1x/cdma.c
index 3995255b16c7..5a8c8d55317a 100644
--- a/drivers/gpu/host1x/cdma.c
+++ b/drivers/gpu/host1x/cdma.c
@@ -97,7 +97,7 @@ fail:
 static void host1x_pushbuffer_push(struct push_buffer *pb, u32 op1, u32 op2)
 {
u32 pos = pb->pos;
-   u32 *p = (u32 *)((u32)pb->mapped + pos);
+   u32 *p = (u32 *)((void *)pb->mapped + pos);
WARN_ON(pos == pb->fence);
*(p++) = op1;
*(p++) = op2;
diff --git a/drivers/gpu/host1x/cdma.h b/drivers/gpu/host1x/cdma.h
index 313c4b784348..470087af8fe5 100644
--- a/drivers/gpu/host1x/cdma.h
+++ b/drivers/gpu/host1x/cdma.h
@@ -42,7 +42,7 @@ struct host1x_job;
  */

 struct push_buffer {
-   u32 *mapped;/* mapped pushbuffer memory */
+   void *mapped;   /* mapped pushbuffer memory */
dma_addr_t phys;/* physical address of pushbuffer */
u32 fence;  /* index we've written */
u32 pos;/* index to write to */
diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c
index 6b09b71940c2..a1197c40a454 100644
--- a/drivers/gpu/host1x/hw/cdma_hw.c
+++ b/drivers/gpu/host1x/hw/cdma_hw.c
@@ -30,7 +30,7 @@
  */
 static void push_buffer_init(struct push_buffer *pb)
 {
-   *(pb->mapped + (pb->size_bytes >> 2)) = host1x_opcode_restart(0);
+   *(u32 *)(pb->mapped + pb->size_bytes) = host1x_opcode_restart(0);
 }

 /*
@@ -51,7 +51,7 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, 
u32 getptr,

/* NOP all the PB slots */
while (nr_slots--) {
-   u32 *p = (u32 *)((u32)pb->mapped + getptr);
+   u32 *p = (u32 *)(pb->mapped + getptr);
*(p++) = HOST1X_OPCODE_NOP;
*(p++) = HOST1X_OPCODE_NOP;
dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__,
-- 
2.1.2



[PATCH 01/14] gpu: host1x: Use struct host1x_bo pointers in traces

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Rather than cast to a u32 use the struct host1x_bo pointers directly.
This avoid annoying warnings for 64-bit builds.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/host1x/hw/channel_hw.c | 12 
 include/trace/events/host1x.h  | 27 +++
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/host1x/hw/channel_hw.c 
b/drivers/gpu/host1x/hw/channel_hw.c
index 4608257ab656..946c332c3906 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -32,6 +32,7 @@
 static void trace_write_gather(struct host1x_cdma *cdma, struct host1x_bo *bo,
   u32 offset, u32 words)
 {
+   struct device *dev = cdma_to_channel(cdma)->dev;
void *mem = NULL;

if (host1x_debug_trace_cmdbuf)
@@ -44,11 +45,14 @@ static void trace_write_gather(struct host1x_cdma *cdma, 
struct host1x_bo *bo,
 * of how much you can output to ftrace at once.
 */
for (i = 0; i < words; i += TRACE_MAX_LENGTH) {
-   trace_host1x_cdma_push_gather(
-   dev_name(cdma_to_channel(cdma)->dev),
-   (u32)bo, min(words - i, TRACE_MAX_LENGTH),
-   offset + i * sizeof(u32), mem);
+   u32 num_words = min(words - i, TRACE_MAX_LENGTH);
+   offset += i * sizeof(u32);
+
+   trace_host1x_cdma_push_gather(dev_name(dev), bo,
+ num_words, offset,
+ mem);
}
+
host1x_bo_munmap(bo, mem);
}
 }
diff --git a/include/trace/events/host1x.h b/include/trace/events/host1x.h
index 94db6a2c3540..63116362543c 100644
--- a/include/trace/events/host1x.h
+++ b/include/trace/events/host1x.h
@@ -29,6 +29,8 @@
 #include 
 #include 

+struct host1x_bo;
+
 DECLARE_EVENT_CLASS(host1x,
TP_PROTO(const char *name),
TP_ARGS(name),
@@ -79,14 +81,14 @@ TRACE_EVENT(host1x_cdma_push,
 );

 TRACE_EVENT(host1x_cdma_push_gather,
-   TP_PROTO(const char *name, u32 mem_id,
+   TP_PROTO(const char *name, struct host1x_bo *bo,
u32 words, u32 offset, void *cmdbuf),

-   TP_ARGS(name, mem_id, words, offset, cmdbuf),
+   TP_ARGS(name, bo, words, offset, cmdbuf),

TP_STRUCT__entry(
__field(const char *, name)
-   __field(u32, mem_id)
+   __field(struct host1x_bo *, bo)
__field(u32, words)
__field(u32, offset)
__field(bool, cmdbuf)
@@ -100,13 +102,13 @@ TRACE_EVENT(host1x_cdma_push_gather,
}
__entry->cmdbuf = cmdbuf;
__entry->name = name;
-   __entry->mem_id = mem_id;
+   __entry->bo = bo;
__entry->words = words;
__entry->offset = offset;
),

-   TP_printk("name=%s, mem_id=%08x, words=%u, offset=%d, contents=[%s]",
- __entry->name, __entry->mem_id,
+   TP_printk("name=%s, bo=%p, words=%u, offset=%d, contents=[%s]",
+ __entry->name, __entry->bo,
  __entry->words, __entry->offset,
  __print_hex(__get_dynamic_array(cmdbuf),
  __entry->cmdbuf ? __entry->words * 4 : 0))
@@ -221,12 +223,13 @@ TRACE_EVENT(host1x_syncpt_load_min,
 );

 TRACE_EVENT(host1x_syncpt_wait_check,
-   TP_PROTO(void *mem_id, u32 offset, u32 syncpt_id, u32 thresh, u32 min),
+   TP_PROTO(struct host1x_bo *bo, u32 offset, u32 syncpt_id, u32 thresh,
+u32 min),

-   TP_ARGS(mem_id, offset, syncpt_id, thresh, min),
+   TP_ARGS(bo, offset, syncpt_id, thresh, min),

TP_STRUCT__entry(
-   __field(void *, mem_id)
+   __field(struct host1x_bo *, bo)
__field(u32, offset)
__field(u32, syncpt_id)
__field(u32, thresh)
@@ -234,15 +237,15 @@ TRACE_EVENT(host1x_syncpt_wait_check,
),

TP_fast_assign(
-   __entry->mem_id = mem_id;
+   __entry->bo = bo;
__entry->offset = offset;
__entry->syncpt_id = syncpt_id;
__entry->thresh = thresh;
__entry->min = min;
),

-   TP_printk("mem_id=%p, offset=%05x, id=%d, thresh=%d, current=%d",
-   __entry->mem_id, __entry->offset,
+   TP_printk("bo=%p, offset=%05x, id=%d, thresh=%d, current=%d",
+   __entry->bo, __entry->offset,
__entry->syncpt_id, __entry->thresh,
__entry->min)
 );
-- 
2.1.2



[PATCH 15/15] drm/panel: Add Sharp LQ101R1SX01 support

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

This panel requires dual-channel mode. The device accepts command-mode
data on 8 lanes and will therefore need a dual-channel DSI controller.
The two interfaces that make up this device need to be instantiated in
the controllers that gang up to provide the dual-channel DSI host.

Signed-off-by: Thierry Reding 
---
 .../bindings/panel/sharp,lq101r1sx01.txt   |  46 +++
 drivers/gpu/drm/panel/Kconfig  |  13 +
 drivers/gpu/drm/panel/Makefile |   1 +
 drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c| 426 +
 4 files changed, 486 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt
 create mode 100644 drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c

diff --git a/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt 
b/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt
new file mode 100644
index ..4ab4380ddac8
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt
@@ -0,0 +1,46 @@
+Sharp Microelectronics 10.1" WQXGA TFT LCD panel
+
+This panel requires a dual-channel DSI host to operate. It supports two modes:
+- left-right: each channel drives the left or right half of the screen
+- even-odd: each channel drives the even or odd lines of the screen
+
+Each of the DSI channels controls a separate DSI peripheral. The peripheral
+driven by the first link (DSI-LINK1), left or even, is considered the primary
+peripheral and controls the device. The 'link2' property contains a phandle
+to the peripheral driven by the second link (DSI-LINK2, right or odd).
+
+Note that in video mode the DSI-LINK1 interface always provides the left/even
+pixels and DSI-LINK2 always provides the right/odd pixels. In command mode it
+is possible to program either link to drive the left/even or right/odd pixels
+but for the sake of consistency this binding assumes that the same assignment
+is chosen as for video mode.
+
+Required properties:
+- compatible: should be "sharp,lq101r1sx01"
+- link2: phandle to the DSI peripheral on the secondary link. Note that the
+  presence of this property marks the containing node as DSI-LINK1.
+- power-supply: phandle of the regulator that provides the supply voltage
+
+Optional properties:
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+
+   dsi at 5430 {
+   panel: panel at 0 {
+   compatible = "sharp,lq101r1sx01";
+   reg = <0>;
+
+   link2 = <>;
+
+   power-supply = <...>;
+   backlight = <...>;
+   };
+   };
+
+   dsi at 5440 {
+   secondary: panel at 0 {
+   compatible = "sharp,lq101r1sx01";
+   reg = <0>;
+   };
+   };
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index bee9f72b3a93..024e98ef8e4d 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -27,4 +27,17 @@ config DRM_PANEL_S6E8AA0
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS

+config DRM_PANEL_SHARP_LQ101R1SX01
+   tristate "Sharp LQ101R1SX01 panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   help
+ Say Y here if you want to enable support for Sharp LQ101R1SX01
+ TFT-LCD modules. The panel has a 2560x1600 resolution and uses
+ 24 bit RGB per pixel. It provides a dual MIPI DSI interface to
+ the host and has a built-in LED backlight.
+
+ To compile this driver as a module, choose M here: the module
+ will be called panel-sharp-lq101r1sx01.
+
 endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 8b929212fad7..4b2a0430804b 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
 obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
 obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
+obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c 
b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
new file mode 100644
index ..09356697d22f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+struct sharp_panel {
+   struct drm_panel base;
+   /* the datasheet refers to them as DSI-LINK1 and DSI-LINK2 */
+   struct mipi_dsi_device *link1;

[PATCH 14/15] drm/dsi: Resolve MIPI DSI device from phandle

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Add a function, of_find_mipi_dsi_device_by_node(), that can be used to
resolve a phandle to a MIPI DSI device.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 23 +++
 include/drm/drm_mipi_dsi.h |  1 +
 2 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index a0b9c7ea77a7..0067f914c1ea 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -67,6 +67,29 @@ static struct bus_type mipi_dsi_bus_type = {
.pm = _dsi_device_pm_ops,
 };

+static int of_device_match(struct device *dev, void *data)
+{
+   return dev->of_node == data;
+}
+
+/**
+ * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
+ *device tree node
+ * @np: device tree node
+ *
+ * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
+ *such device exists (or has not been registered yet).
+ */
+struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
+{
+   struct device *dev;
+
+   dev = bus_find_device(_dsi_bus_type, NULL, np, of_device_match);
+
+   return dev ? to_mipi_dsi_device(dev) : NULL;
+}
+EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
+
 static void mipi_dsi_dev_release(struct device *dev)
 {
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 17ef2fbb09a5..8f025cc5ce99 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -142,6 +142,7 @@ static inline struct mipi_dsi_device 
*to_mipi_dsi_device(struct device *dev)
return container_of(dev, struct mipi_dsi_device, dev);
 }

+struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node 
*np);
 int mipi_dsi_attach(struct mipi_dsi_device *dsi);
 int mipi_dsi_detach(struct mipi_dsi_device *dsi);
 int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
-- 
2.1.2



[PATCH 13/15] drm/dsi: Always use low-power mode for DCS commands

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Many peripherals require DCS commands to be sent in low power mode and
will fail to correctly process them in high speed mode. Section 5.2 of
the MIPI DSI specification also mandates that on bidirectional lanes,
data shall be transmitted in low power mode only. At worst this change
will make transmission of DCS commands slower than optimal on some DSI
peripherals, but it should enable DCS commands to be successfully
transmitted to any DSI peripheral.

If transmission in low power mode turns out to be too slow at some point
in the future, one possible solution would be to explicitly mark devices
that support high speed transmission of DCS commands.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index d4d3cf752be7..a0b9c7ea77a7 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -370,6 +370,7 @@ ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device 
*dsi,
 {
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
+   .flags = MIPI_DSI_MSG_USE_LPM,
.tx_buf = data,
.tx_len = len
};
@@ -457,6 +458,7 @@ ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 
cmd,
}

memset(, 0, sizeof(msg));
+   msg.flags = MIPI_DSI_MSG_USE_LPM;
msg.channel = dsi->channel;
msg.tx_len = size;
msg.tx_buf = tx;
@@ -500,6 +502,7 @@ ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 
cmd, void *data,
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.type = MIPI_DSI_DCS_READ,
+   .flags = MIPI_DSI_MSG_USE_LPM,
.tx_buf = ,
.tx_len = 1,
.rx_buf = data,
-- 
2.1.2



[PATCH 12/15] drm/dsi: Implement DCS set_{column, page}_address commands

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Provide small convenience wrappers to set the column and page extents of
the frame memory accessed by the host processors.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 46 ++
 include/drm/drm_mipi_dsi.h |  4 
 2 files changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index d7ca57f1fdd3..d4d3cf752be7 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -671,6 +671,52 @@ int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device 
*dsi)
 EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);

 /**
+ * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
+ *memory accessed by the host processor
+ * @dsi: DSI peripheral device
+ * @start: first column of frame memory
+ * @end: last column of frame memory
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
+   u16 end)
+{
+   u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
+sizeof(payload));
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+
+/**
+ * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
+ *memory accessed by the host processor
+ * @dsi: DSI peripheral device
+ * @start: first page of frame memory
+ * @end: last page of frame memory
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
+ u16 end)
+{
+   u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
+sizeof(payload));
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+
+/**
  * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
  *output signal on the TE signal line
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 968085b1ef73..17ef2fbb09a5 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -184,6 +184,10 @@ int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device 
*dsi);
 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi);
+int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
+   u16 end);
+int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
+ u16 end);
 int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
 enum mipi_dsi_dcs_tear_mode mode);
-- 
2.1.2



[PATCH 11/15] drm/dsi: Implement DCS {get,set}_pixel_format commands

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Provide small convenience wrappers to query or set the pixel format used
by the interface.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 42 ++
 include/drm/drm_mipi_dsi.h |  2 ++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 4e016a6a9fc3..d7ca57f1fdd3 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -574,6 +574,27 @@ int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device 
*dsi, u8 *mode)
 EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);

 /**
+ * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
+ *data used by the interface
+ * @dsi: DSI peripheral device
+ * @format: return location for the pixel format
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
+   sizeof(*format));
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
+
+/**
  * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
  *display module except interface communication
  * @dsi: DSI peripheral device
@@ -691,6 +712,27 @@ int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);

+/**
+ * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
+ *data used by the interface
+ * @dsi: DSI peripheral device
+ * @format: pixel format
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, ,
+sizeof(format));
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
+
 static int mipi_dsi_drv_probe(struct device *dev)
 {
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index b659b99ac890..968085b1ef73 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -179,6 +179,7 @@ ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 
cmd, void *data,
 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode);
+int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format);
 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
@@ -186,6 +187,7 @@ int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device 
*dsi);
 int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
 enum mipi_dsi_dcs_tear_mode mode);
+int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);

 /**
  * struct mipi_dsi_driver - DSI driver
-- 
2.1.2



[PATCH 10/15] drm/dsi: Implement DCS get_power_mode command

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Provide a small convenience wrapper that transmits a DCS get_power_mode
command. A set of bitmasks for the mode bits is also provided.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 21 +
 include/drm/drm_mipi_dsi.h |  7 +++
 2 files changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 60bd68b520ae..4e016a6a9fc3 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -553,6 +553,27 @@ int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
 EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);

 /**
+ * mipi_dsi_dcs_get_power_mode() - query the display module's current power
+ *mode
+ * @dsi: DSI peripheral device
+ * @mode: return location for the current power mode
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
+   sizeof(*mode));
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
+
+/**
  * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
  *display module except interface communication
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 2afbd5853f78..b659b99ac890 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -164,6 +164,12 @@ enum mipi_dsi_dcs_tear_mode {
MIPI_DSI_DCS_TEAR_MODE_VHBLANK,
 };

+#define MIPI_DSI_DCS_POWER_MODE_DISPLAY (1 << 2)
+#define MIPI_DSI_DCS_POWER_MODE_NORMAL  (1 << 3)
+#define MIPI_DSI_DCS_POWER_MODE_SLEEP   (1 << 4)
+#define MIPI_DSI_DCS_POWER_MODE_PARTIAL (1 << 5)
+#define MIPI_DSI_DCS_POWER_MODE_IDLE(1 << 6)
+
 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
  const void *data, size_t len);
 ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
@@ -172,6 +178,7 @@ ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 
cmd, void *data,
  size_t len);
 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi);
+int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode);
 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
-- 
2.1.2



[PATCH 09/15] drm/dsi: Implement DCS soft_reset command

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Provide a small convenience wrapper that transmits a DCS soft_reset
command.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 18 ++
 include/drm/drm_mipi_dsi.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index c88dcda2f4ac..60bd68b520ae 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -535,6 +535,24 @@ int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
 EXPORT_SYMBOL(mipi_dsi_dcs_nop);

 /**
+ * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
+
+/**
  * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
  *display module except interface communication
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index be16c8e769bd..2afbd5853f78 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -171,6 +171,7 @@ ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 
cmd,
 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
  size_t len);
 int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi);
+int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
-- 
2.1.2



[PATCH 08/15] drm/dsi: Implement DCS nop command

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Provide a small convenience wrapper that transmits a DCS nop command.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 18 ++
 include/drm/drm_mipi_dsi.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 6749b88a6c72..c88dcda2f4ac 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -517,6 +517,24 @@ ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 
cmd, void *data,
 EXPORT_SYMBOL(mipi_dsi_dcs_read);

 /**
+ * mipi_dsi_dcs_nop() - send DCS nop packet
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_nop);
+
+/**
  * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
  *display module except interface communication
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 8693711eb623..be16c8e769bd 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -170,6 +170,7 @@ ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 
cmd,
   const void *data, size_t len);
 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
  size_t len);
+int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
 int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
-- 
2.1.2



[PATCH 07/15] drm/dsi: Add to DocBook documentation

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Integrate the MIPI DSI helpers into DocBook and clean up various
kerneldoc warnings. Also add a brief DOC section and clarify some
aspects of the mipi_dsi_host struct's .transfer() operation.

Signed-off-by: Thierry Reding 
---
 Documentation/DocBook/drm.tmpl |  6 ++
 drivers/gpu/drm/drm_mipi_dsi.c | 18 --
 include/drm/drm_mipi_dsi.h | 16 ++--
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index be35bc328b77..da733c28c92f 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -2343,6 +2343,12 @@ void intel_crt_init(struct drm_device *dev)
 !Edrivers/gpu/drm/drm_dp_mst_topology.c
 
 
+  MIPI DSI Helper Functions Reference
+!Pdrivers/gpu/drm/drm_mipi_dsi.c dsi helpers
+!Iinclude/drm/drm_mipi_dsi.h
+!Edrivers/gpu/drm/drm_mipi_dsi.c
+
+
   EDID Helper Functions Reference
 !Edrivers/gpu/drm/drm_edid.c
 
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 8bb38db861ec..6749b88a6c72 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -35,6 +35,16 @@

 #include 

+/**
+ * DOC: dsi helpers
+ *
+ * These functions contain some common logic and helpers to deal with MIPI DSI
+ * peripherals.
+ *
+ * Helpers are provided for a number of standard MIPI DSI command as well as a
+ * subset of the MIPI DCS command set.
+ */
+
 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
 {
return of_driver_match_device(dev, drv);
@@ -649,8 +659,10 @@ static void mipi_dsi_drv_shutdown(struct device *dev)
 }

 /**
- * mipi_dsi_driver_register - register a driver for DSI devices
+ * mipi_dsi_driver_register() - register a driver for DSI devices
  * @drv: DSI driver structure
+ *
+ * Return: 0 on success or a negative error code on failure.
  */
 int mipi_dsi_driver_register(struct mipi_dsi_driver *drv)
 {
@@ -667,8 +679,10 @@ int mipi_dsi_driver_register(struct mipi_dsi_driver *drv)
 EXPORT_SYMBOL(mipi_dsi_driver_register);

 /**
- * mipi_dsi_driver_unregister - unregister a driver for DSI devices
+ * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
  * @drv: DSI driver structure
+ *
+ * Return: 0 on success or a negative error code on failure.
  */
 void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
 {
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index bde663725a58..8693711eb623 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -26,6 +26,7 @@ struct mipi_dsi_device;
  * struct mipi_dsi_msg - read/write DSI buffer
  * @channel: virtual channel id
  * @type: payload data type
+ * @flags: flags controlling this message transmission
  * @tx_len: length of @tx_buf
  * @tx_buf: data to be written
  * @rx_len: length of @rx_buf
@@ -47,8 +48,19 @@ struct mipi_dsi_msg {
  * struct mipi_dsi_host_ops - DSI bus operations
  * @attach: attach DSI device to DSI host
  * @detach: detach DSI device from DSI host
- * @transfer: send and/or receive DSI packet, return number of received bytes,
- *   or error
+ * @transfer: transmit a DSI packet
+ *
+ * DSI packets transmitted by .transfer() are passed in as mipi_dsi_msg
+ * structures. This structure contains information about the type of packet
+ * being transmitted as well as the transmit and receive buffers. When an
+ * error is encountered during transmission, this function will return a
+ * negative error code. On success it shall return the number of bytes
+ * transmitted for write packets or the number of bytes received for read
+ * packets.
+ *
+ * Note that typically DSI packet transmission is atomic, so the .transfer()
+ * function will seldomly return anything other than the number of bytes
+ * contained in the transmit buffer on success.
  */
 struct mipi_dsi_host_ops {
int (*attach)(struct mipi_dsi_host *host,
-- 
2.1.2



[PATCH 06/15] drm/dsi: Implement some standard DCS commands

2014-10-13 Thread Thierry Reding
From: YoungJun Cho 

Add helpers for the {enter,exit}_sleep_mode, set_display_{on,off} and
set_tear_{on,off} DCS commands.

Signed-off-by: YoungJun Cho 
[treding: kerneldoc and other minor cleanup]
Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 118 +
 include/drm/drm_mipi_dsi.h |  19 +++
 2 files changed, 137 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 7cd69273dbad..8bb38db861ec 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -506,6 +506,124 @@ ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 
cmd, void *data,
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_read);

+/**
+ * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
+ *display module except interface communication
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
+
+/**
+ * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
+ *module
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
+
+/**
+ * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
+ *display device
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
+
+/**
+ * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
+ *display device
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure
+ */
+int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
+
+/**
+ * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
+ *output signal on the TE signal line
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure
+ */
+int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
+{
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
+
+/**
+ * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
+ *output signal on the TE signal line.
+ * @dsi: DSI peripheral device
+ * @mode: the Tearing Effect Output Line mode
+ *
+ * Return: 0 on success or a negative error code on failure
+ */
+int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
+enum mipi_dsi_dcs_tear_mode mode)
+{
+   u8 value = mode;
+   ssize_t err;
+
+   err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, ,
+sizeof(value));
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
+
 static int mipi_dsi_drv_probe(struct device *dev)
 {
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 92ca66306702..bde663725a58 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -140,12 +140,31 @@ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device 
*dsi, const void *payload,
 ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
  size_t num_params, void *data, size_t size);

+/**
+ * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode
+ * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking
+ *information only
+ * @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both
+ *V-Blanking and H-Blanking information
+ */
+enum mipi_dsi_dcs_tear_mode {
+   MIPI_DSI_DCS_TEAR_MODE_VBLANK,
+   MIPI_DSI_DCS_TEAR_MODE_VHBLANK,
+};
+
 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
  const void *data, size_t 

[PATCH 05/15] drm/dsi: Implement generic read and write commands

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Implement generic read and write commands. Selection of the proper data
type for packets is done automatically based on the number of parameters
or payload length.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 115 +
 include/drm/drm_mipi_dsi.h |   6 +++
 2 files changed, 121 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 27fc6dac5e4a..7cd69273dbad 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -229,6 +229,121 @@ int mipi_dsi_set_maximum_return_packet_size(struct 
mipi_dsi_device *dsi,
 EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);

 /**
+ * mipi_dsi_generic_write() - transmit data using a generic write packet
+ * @dsi: DSI peripheral device
+ * @payload: buffer containing the payload
+ * @size: size of payload buffer
+ *
+ * This function will automatically choose the right data type depending on
+ * the payload length.
+ *
+ * Return: The number of bytes transmitted on success or a negative error code
+ * on failure.
+ */
+ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void 
*payload,
+  size_t size)
+{
+   struct mipi_dsi_msg msg;
+   ssize_t err;
+   u8 *tx;
+
+   memset(, 0, sizeof(msg));
+   msg.channel = dsi->channel;
+   msg.flags = MIPI_DSI_MSG_USE_LPM | MIPI_DSI_MSG_REQ_ACK;
+
+   if (size > 2) {
+   tx = kmalloc(2 + size, GFP_KERNEL);
+   if (!tx)
+   return -ENOMEM;
+
+   tx[0] = (size >> 0) & 0xff;
+   tx[1] = (size >> 8) & 0xff;
+
+   memcpy(tx + 2, payload, size);
+
+   msg.tx_len = 2 + size;
+   msg.tx_buf = tx;
+   } else {
+   msg.tx_buf = payload;
+   msg.tx_len = size;
+   }
+
+   switch (size) {
+   case 0:
+   msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
+   break;
+
+   case 1:
+   msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
+   break;
+
+   case 2:
+   msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
+   break;
+
+   default:
+   msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
+   break;
+   }
+
+   err = dsi->host->ops->transfer(dsi->host, );
+
+   if (size > 2)
+   kfree(tx);
+
+   return err;
+}
+EXPORT_SYMBOL(mipi_dsi_generic_write);
+
+/**
+ * mipi_dsi_generic_read() - receive data using a generic read packet
+ * @dsi: DSI peripheral device
+ * @params: buffer containing the request parameters
+ * @num_params: number of request parameters
+ * @data: buffer in which to return the received data
+ * @size: size of receive buffer
+ *
+ * This function will automatically choose the right data type depending on
+ * the number of parameters passed in.
+ *
+ * Return: The number of bytes successfully read or a negative error code on
+ * failure.
+ */
+ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
+ size_t num_params, void *data, size_t size)
+{
+   struct mipi_dsi_msg msg;
+
+   memset(, 0, sizeof(msg));
+   msg.channel = dsi->channel;
+   msg.flags = MIPI_DSI_MSG_USE_LPM;
+   msg.tx_len = num_params;
+   msg.tx_buf = params;
+   msg.rx_len = size;
+   msg.rx_buf = data;
+
+   switch (num_params) {
+   case 0:
+   msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
+   break;
+
+   case 1:
+   msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+   break;
+
+   case 2:
+   msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
+   break;
+
+   default:
+   return -EINVAL;
+   }
+
+   return dsi->host->ops->transfer(dsi->host, );
+}
+EXPORT_SYMBOL(mipi_dsi_generic_read);
+
+/**
  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
  * @dsi: DSI peripheral device
  * @data: buffer containing data to be transmitted
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index ef50b5d0de57..92ca66306702 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -134,6 +134,12 @@ int mipi_dsi_attach(struct mipi_dsi_device *dsi);
 int mipi_dsi_detach(struct mipi_dsi_device *dsi);
 int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
+
+ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void 
*payload,
+  size_t size);
+ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
+ size_t num_params, void *data, size_t size);
+
 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
  const void 

[PATCH 04/15] drm/panel: s6e8aa0: Use standard MIPI DSI function

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Use the newly introduced mipi_dsi_set_maximum_return_packet_size()
function to replace an open-coded version.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/panel/panel-s6e8aa0.c | 16 ++--
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-s6e8aa0.c 
b/drivers/gpu/drm/panel/panel-s6e8aa0.c
index 0f85a7c37687..c31e2953f290 100644
--- a/drivers/gpu/drm/panel/panel-s6e8aa0.c
+++ b/drivers/gpu/drm/panel/panel-s6e8aa0.c
@@ -800,27 +800,15 @@ static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
 }

 static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
-  int size)
+  u16 size)
 {
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
-   const struct mipi_dsi_host_ops *ops = dsi->host->ops;
-   u8 buf[] = {size, 0};
-   struct mipi_dsi_msg msg = {
-   .channel = dsi->channel,
-   .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
-   .tx_len = sizeof(buf),
-   .tx_buf = buf
-   };
int ret;

if (ctx->error < 0)
return;

-   if (!ops || !ops->transfer)
-   ret = -EIO;
-   else
-   ret = ops->transfer(dsi->host, );
-
+   ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
if (ret < 0) {
dev_err(ctx->dev,
"error %d setting maximum return packet size to %d\n",
-- 
2.1.2



[PATCH 03/15] drm/dsi: Add mipi_dsi_set_maximum_return_packet_size() helper

2014-10-13 Thread Thierry Reding
From: YoungJun Cho 

This function can be used to set the maximum return packet size for a
MIPI DSI peripheral.

Signed-off-by: YoungJun Cho 
[treding: endianess, kerneldoc, return value]
Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_mipi_dsi.c | 30 ++
 include/drm/drm_mipi_dsi.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 1702ffd07986..27fc6dac5e4a 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -198,6 +198,36 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
 }
 EXPORT_SYMBOL(mipi_dsi_detach);

+/*
+ * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
+ *the payload in a long packet transmitted from the peripheral back to the
+ *host processor
+ * @dsi: DSI peripheral device
+ * @value: the maximum size of the payload
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
+   u16 value)
+{
+   u8 tx[2] = { value & 0xff, value >> 8 };
+   struct mipi_dsi_msg msg;
+   ssize_t err;
+
+   memset(, 0, sizeof(msg));
+   msg.channel = dsi->channel;
+   msg.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE;
+   msg.tx_len = sizeof(tx);
+   msg.tx_buf = tx;
+
+   err = dsi->host->ops->transfer(dsi->host, );
+   if (err < 0)
+   return err;
+
+   return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
+
 /**
  * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
  * @dsi: DSI peripheral device
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 836cc2b677d0..ef50b5d0de57 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -132,6 +132,8 @@ static inline struct mipi_dsi_device 
*to_mipi_dsi_device(struct device *dev)

 int mipi_dsi_attach(struct mipi_dsi_device *dsi);
 int mipi_dsi_detach(struct mipi_dsi_device *dsi);
+int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
+   u16 value);
 ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
  const void *data, size_t len);
 ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
-- 
2.1.2



[PATCH 02/15] drm/dsi: Constify mipi_dsi_msg

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

struct mipi_dsi_msg is a read-only structure, drivers should never need
to modify it. Make this explicit by making all references to the struct
const.

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 +-
 include/drm/drm_mipi_dsi.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 24741d8758e8..c5f3c76bfac3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1236,7 +1236,7 @@ static bool exynos_dsi_is_short_dsi_type(u8 type)
 }

 static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host,
-  struct mipi_dsi_msg *msg)
+   const struct mipi_dsi_msg *msg)
 {
struct exynos_dsi *dsi = host_to_dsi(host);
struct exynos_dsi_transfer xfer;
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index ccc3869e137b..836cc2b677d0 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -56,7 +56,7 @@ struct mipi_dsi_host_ops {
int (*detach)(struct mipi_dsi_host *host,
  struct mipi_dsi_device *dsi);
ssize_t (*transfer)(struct mipi_dsi_host *host,
-   struct mipi_dsi_msg *msg);
+   const struct mipi_dsi_msg *msg);
 };

 /**
-- 
2.1.2



[PATCH v2 01/15] drm/dsi: Make mipi_dsi_dcs_{read, write}() symmetrical

2014-10-13 Thread Thierry Reding
From: Thierry Reding 

Currently the mipi_dsi_dcs_write() function requires the DCS command
byte to be embedded within the write buffer whereas mipi_dsi_dcs_read()
has a separate parameter. Make them more symmetrical by adding an extra
command parameter to mipi_dsi_dcs_write().

The S6E8AA0 driver relies on the old asymmetric API and there's concern
that moving to the new API may be less efficient. Provide a new function
with the old semantics for those cases and make the S6E8AA0 driver use
it instead.

Signed-off-by: Thierry Reding 
---
Changes in v2:
- provide mipi_dsi_dcs_write_buffer() for backwards compatibility

 drivers/gpu/drm/drm_mipi_dsi.c| 127 +-
 drivers/gpu/drm/panel/panel-s6e8aa0.c |   2 +-
 include/drm/drm_mipi_dsi.h|   6 +-
 3 files changed, 114 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index eb6dfe52cab2..1702ffd07986 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -199,33 +199,120 @@ int mipi_dsi_detach(struct mipi_dsi_device *dsi)
 EXPORT_SYMBOL(mipi_dsi_detach);

 /**
- * mipi_dsi_dcs_write - send DCS write command
- * @dsi: DSI device
- * @data: pointer to the command followed by parameters
- * @len: length of @data
+ * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
+ * @dsi: DSI peripheral device
+ * @data: buffer containing data to be transmitted
+ * @len: size of transmission buffer
+ *
+ * This function will automatically choose the right data type depending on
+ * the command payload length.
+ *
+ * Return: The number of bytes successfully transmitted or a negative error
+ * code on failure.
  */
-ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, const void *data,
-   size_t len)
+ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
+ const void *data, size_t len)
 {
-   const struct mipi_dsi_host_ops *ops = dsi->host->ops;
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = data,
.tx_len = len
};

-   if (!ops || !ops->transfer)
+   if (!dsi->host->ops || !dsi->host->ops->transfer)
return -ENOSYS;

switch (len) {
case 0:
return -EINVAL;
+
case 1:
msg.type = MIPI_DSI_DCS_SHORT_WRITE;
break;
+
case 2:
msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
break;
+
+   default:
+   msg.type = MIPI_DSI_DCS_LONG_WRITE;
+   break;
+   }
+
+   return dsi->host->ops->transfer(dsi->host, );
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
+
+/**
+ * mipi_dsi_dcs_write() - send DCS write command
+ * @dsi: DSI peripheral device
+ * @cmd: DCS command
+ * @data: buffer containing the command payload
+ * @len: command payload length
+ *
+ * This function will automatically choose the right data type depending on
+ * the command payload length.
+ *
+ * Return: The number of bytes successfully transmitted or a negative error
+ * code on failure.
+ */
+ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
+  const void *data, size_t len)
+{
+   struct mipi_dsi_msg msg;
+   ssize_t err;
+   size_t size;
+   u8 *tx;
+
+   if (!dsi->host->ops || !dsi->host->ops->transfer)
+   return -ENOSYS;
+
+   if (len > 0) {
+   unsigned int offset = 0;
+
+   /*
+* DCS long write packets contain the word count in the header
+* bytes 1 and 2 and have a payload containing the DCS command
+* byte folowed by word count minus one bytes.
+*
+* DCS short write packets encode the DCS command and up to
+* one parameter in header bytes 1 and 2.
+*/
+   if (len > 1)
+   size = 3 + len;
+   else
+   size = 1 + len;
+
+   tx = kmalloc(size, GFP_KERNEL);
+   if (!tx)
+   return -ENOMEM;
+
+   /* write word count to header for DCS long write packets */
+   if (len > 1) {
+   tx[offset++] = ((1 + len) >> 0) & 0xff;
+   tx[offset++] = ((1 + len) >> 8) & 0xff;
+   }
+
+   /* write the DCS command byte followed by the payload */
+   tx[offset++] = cmd;
+   memcpy(tx + offset, data, len);
+   } else {
+   tx = 
+   size = 1;
+   }
+
+   memset(, 0, sizeof(msg));
+   msg.channel = dsi->channel;
+   msg.tx_len = size;
+   msg.tx_buf = tx;
+
+   switch (len) {
+   case 0:
+   msg.type = MIPI_DSI_DCS_SHORT_WRITE;
+   break;
+   case 1:
+  

FirePro W600 problem

2014-10-13 Thread Alex Deucher
On Wed, Oct 8, 2014 at 4:41 PM, Andrey Germakovski
 wrote:
> FirePro W600 does not work with more than 4 monitors,
>
>
>
> After 5th  monitor attached X acting very slow.
>
>
>
> Or if I call drmModeSetCrtc function 5 times one time for each of the
> monitors, it failing out

I suspect you are running out of CPU accessible vram depending on your
configuration.  There are patches for mesa and the kernel to allow the
use of non-CPU accessible vram for display buffers in kernel 3.17 and
mesa git so you might try a newer kernel and mesa.

Alex


'drop clk/voltage dependency filters for SI' breaks factory-over-clocked Cape Verde

2014-10-13 Thread Alex Deucher
On Wed, Oct 8, 2014 at 11:21 PM, Michel D?nzer  wrote:
>
> Hi Alex,
>
>
> your kernel commit 186b1b2ba2a0684e3d2d3703427a993a3b35b16d
> ('drm/radeon/dpm: drop clk/voltage dependency filters for SI') causes my
> factory-over-clocked Cape Verde card to lock up pretty quickly when running
> e.g. Unigine Valley or the PTS Xonotic benchmark. Everything's fine again
> after reverting that commit and the one which removed
> btc_get_max_clock_from_voltage_dependency_table.

Reverted in my tree.

Alex


[Linaro-mm-sig] [RFC 1/4] dma-buf: Add constraints sharing information

2014-10-13 Thread Daniel Vetter
On Mon, Oct 13, 2014 at 01:14:58AM -0700, Laura Abbott wrote:
> On 10/11/2014 11:55 AM, Daniel Vetter wrote:
> >On Sat, Oct 11, 2014 at 01:37:55AM +0530, Sumit Semwal wrote:
> >>At present, struct device lacks a mechanism of exposing memory
> >>access constraints for the device.
> >>
> >>Consequently, there is also no mechanism to share these constraints
> >>while sharing buffers using dma-buf.
> >>
> >>If we add support for sharing such constraints, we could use that
> >>to try to collect requirements of different buffer-sharing devices
> >>to allocate buffers from a pool that satisfies requirements of all
> >>such devices.
> >>
> >>This is an attempt to add this support; at the moment, only a bitmask
> >>is added, but if post discussion, we realise we need more information,
> >>we could always extend the definition of constraint.
> >>
> >>A new dma-buf op is also added, to allow exporters to interpret or decide
> >>on constraint-masks on their own. A default implementation is provided to
> >>just AND (&) all the constraint-masks.
> >>
> >>What constitutes a constraint-mask could be left for interpretation on a
> >>per-platform basis, while defining some common masks.
> >>
> >>Signed-off-by: Sumit Semwal 
> >>Cc: linux-kernel at vger.kernel.org
> >>Cc: Greg Kroah-Hartman 
> >>Cc: linux-media at vger.kernel.org
> >>Cc: dri-devel at lists.freedesktop.org
> >>Cc: linaro-mm-sig at lists.linaro.org
> >
> >Just a few high-level comments, I'm between conference travel but
> >hopefully I can discuss this a bit at plumbers next week.
> >
> >- I agree that for the insane specific cases we need something opaque like
> >   the access constraints mask you propose here. But for the normal case I
> >   think the existing dma constraints in dma_params would go a long way,
> >   and I think we should look at Rob's RFC from aeons ago to solve those:
> >
> >   https://lkml.org/lkml/2012/7/19/285
> >
> >   With this we should be able to cover the allocation constraints of 90%
> >   of all cases hopefully.
> >
> >- I'm not sure whether an opaque bitmask is good enough really, I suspect
> >   that we also need various priorities between different allocators. With
> >   the option that some allocators are flat-out incompatible.
> >
> 
> From my experience with Ion, the bitmask is okay if you have only a few
> types but as soon as there are multiple regions it gets complicated and
> when you start adding in priority via id it really gets unwieldy.

My idea is to just have a priority field for all devices which have
special requirements (i.e. beyond dma masks/alignement/segment limits).
Same priority on different devices would indicate an incompatibility, but
higher priority on a parent device would indicate a possible allocator.
That way you could have a root allocator if there's a way to unify
everything. Not sure though whether this will work, since on intel devices
we just don't have these kinds of special constraints.

Overall my idea is to reuse the existing dma allocation code in upstream
linux as much as possible. So having a completely separate hirarchy of
memory allocators for shared buffers should imo be avoided.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH v2] gpu: drm: drm_dp_mst_topology.c: Fix improper use of strncat

2014-10-13 Thread Jani Nikula
On Sun, 12 Oct 2014, Rickard Strandqvist  wrote:
> Fixed wrong usage of strncat, switched to strlcpy.
> While sending the string size to function to reduce
> the potential for misuse in future.
>
> Signed-off-by: Rickard Strandqvist 

Reviewed-by: Jani Nikula 

> ---
>  drivers/gpu/drm/drm_dp_mst_topology.c |   15 ---
>  1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
> b/drivers/gpu/drm/drm_dp_mst_topology.c
> index ac3c273..2a146d1 100644
> --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> @@ -995,19 +995,20 @@ static void drm_dp_check_port_guid(struct 
> drm_dp_mst_branch *mstb,
>  
>  static void build_mst_prop_path(struct drm_dp_mst_port *port,
>   struct drm_dp_mst_branch *mstb,
> - char *proppath)
> + char *proppath,
> + size_t proppath_size)
>  {
>   int i;
>   char temp[8];
> - snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id);
> + snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
>   for (i = 0; i < (mstb->lct - 1); i++) {
>   int shift = (i % 2) ? 0 : 4;
>   int port_num = mstb->rad[i / 2] >> shift;
> - snprintf(temp, 8, "-%d", port_num);
> - strncat(proppath, temp, 255);
> + snprintf(temp, sizeof(temp), "-%d", port_num);
> + strlcat(proppath, temp, proppath_size);
>   }
> - snprintf(temp, 8, "-%d", port->port_num);
> - strncat(proppath, temp, 255);
> + snprintf(temp, sizeof(temp), "-%d", port->port_num);
> + strlcat(proppath, temp, proppath_size);
>  }
>  
>  static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
> @@ -1078,7 +1079,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
> *mstb,
>  
>   if (created && !port->input) {
>   char proppath[255];
> - build_mst_prop_path(port, mstb, proppath);
> + build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
>   port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, 
> port, proppath);
>   }
>  
> -- 
> 1.7.10.4
>
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Jani Nikula, Intel Open Source Technology Center


[Bulk] Re: [3.16-rcX][pciehp][radeon] PCIe HotPlug conflicts with radeon GPU

2014-10-13 Thread Bjorn Helgaas
[+cc Alex, Christian, dri-devel]

On Sat, Oct 11, 2014 at 1:37 PM, Shawn Starr  wrote:
> On September 11, 2014 04:26:21 PM Bjorn Helgaas wrote:
>> [+cc linux-pci]
>>
>> On Sat, Aug 2, 2014 at 10:02 AM, Shawn Starr  
>> wrote:
>> > Hello devs,
>> >
>> > There are two issues I am encountering with the PCIe Hotplug driver on my
>> > Lenovo Laptop (W500). I note this goes back further than 3.15.
>> >
>> > It is noted here:
>> > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=
>> > f244d8b623dae7a7bc695b0336f67729b95a9736
>> > https://bugzilla.kernel.org/show_bug.cgi?id=79701
>> >
>> > And my open bug here:
>> > https://bugzilla.kernel.org/show_bug.cgi?id=77261
>> >
>> > 1) If I enable the device to use both the integrated and discrete GPU,
>> > pciehp will decide to force unload radeon because it puts itself into a
>> > power saving state, fails back to the Intel integrated GPU in this case
>> > unless I tell radeon.ko to runpm=0 (no power management, then pciehp wont
>> > touch it).
>> >
>> > 2) If the Radeon GPU resets and you use pci_reset=1 for kernel module
>> > option, pciehp decides to force unload radeon even though the GPU is
>> > trying to setup after failing.
>> >
>> > Kernel I am using right now: 3.16.0-0.rc7.git3.1.fc21.x86_64 (about to
>> > boot into snapshot kernel-core-3.16.0-0.rc7.git4.1.fc21.x86_64)
>> Hi Shawn,
>>
>> Thanks for the report and sorry that it got dropped.  But I see you're
>> cc'd on https://bugzilla.kernel.org/show_bug.cgi?id=79701, so you've
>> probably seen the work there.  If you can try out the patches I just
>> posted, that would be great.
>>
>> Bjorn
>
> Hi Bjorn,
>
> For #1) This is fixed in linux-next (tracking 
> 3.18.0-0.rc0.git1.2.fc22.1.x86_64
> nondebug kernel for Fedora). PCIe HotPlug no longer unloads radeon. For this
> bugzilla report we can close it.
>
> #2) This still has weird results however, radeon.hard_reset=1 is experimental
> and while it attempts to reset GPU, PCIe HotPlug seems to interact in this.
>
> This can be tested by adding to grub command line radeon.hard_reset=1.
> When X has started up, trigger a reset by cat
> /sys/kernel/debug/dri/#/radeon_gpu_reset. It will output 0, cat it again will
> show 1.
>
> Attempt to drag a window. The this will trigger a GPU reset, but fail to
> recover, its unknown if PCIe HotPlug is preventing a proper reset or not but
> there is pciehp calls in the stack trace.

A PCIe device reset usually looks like a hotplug event because the
PCIe link goes down and comes back up.  As far as the PCI core is
concerned, it can't tell the difference between (1) a simple reset
where the link bounces and (2) removal of one device followed by
addition of another.

b440bde74f04 ("PCI: Add pci_ignore_hotplug() to ignore hotplug events
for a device") addressed this for some similar cases, but it looks
like we probably need some more calls to pci_ignore_hotplug() in the
radeon driver reset methods.

Can you please open a bugzilla and attach the complete dmesg log,
including the GPU reset and recovery failure?

Bjorn


[Bug 79980] Random radeonsi crashes

2014-10-13 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=79980

--- Comment #159 from Malte Schr?der  ---
VDPAU doesn't make a difference, still crashes.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/cf1a0f74/attachment.html>


[PATCH] drm: drm_err: Remove unnecessary __func__ argument

2014-10-13 Thread Joe Perches
On Mon, 2014-10-13 at 17:46 +0200, David Herrmann wrote:
> Hi
> 
> On Sun, Oct 12, 2014 at 7:08 AM, Joe Perches  wrote:
> > Removing the unnecessary drm_err __func__ argument by using
> > the equivalent %pf and __builtin_return_address(0) makes the
> > code smaller for every use of the DRM_ERROR macro.
> >
> > For instance: (allmodconfig)
> >
> > $ size drivers/gpu/drm/i915/i915.o*
> >textdata bss dec hex filename
> >  922447  193257  296736 1412440  158d58 drivers/gpu/drm/i915/i915.o.new
> >  928111  193257  296736 1418104  15a378 drivers/gpu/drm/i915/i915.o.old
> 
> You might want to mention that this requires a binary-search through
> kallsyms on each call.

All these calls are infrequently taken error paths
and the cost of the printk itself is _far_ higher
than a binary search for the symbol.

> I guess that's the reason you didn't use it for
> drm_ut_debug_printk()? I'm fine with doing this on drm_err(). Looks
> good.

No, the reason I didn't do it there is that those calls
should really be consolidated and be able to use dynamic_debug.
It'd be a separate patch.

cheers, Joe



[Bug 79980] Random radeonsi crashes

2014-10-13 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=79980

--- Comment #158 from Malte Schr?der  ---
(In reply to agapito from comment #157)
> (In reply to Malte Schr?der from comment #156)
> >> I've set aspm=0 for the radeon module and the system has been running for
> > some hours straight.
> 
> Not for me.

Yeah, it just crashed on me again. So I was just lucky. I also tried disabling
dynclks and dpm, no effect. What I did differently yesterday is I had very
litte browser (Debian Iceweasel) usage. Today I had some Youtube running when
the crash happened. In fact the crashes happen most time when whatching stuff
on Youtube, i.e. when Iceweasel uses vdpau through gstreamer. I now removed
mesa vdpau drivers. I will report back if this changes anything.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/02f1e30f/attachment-0001.html>


[Bug 84500] [radeonsi] radeon 0000:01:00.0: Packet0 not allowed!

2014-10-13 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=84500

--- Comment #24 from Alexandre Demers  ---
(In reply to Alexandre Demers from comment #23)
> (In reply to Christian K?nig from comment #22)
> > Keep in mind that this might actually be a user space problem and that
> > different kernel versions work or don't work only be coincident.
> > 
> > If you can get me an SSH access to the box I could take a look as well.
> > Attaching a debugger to the process in question shouldn't be to hard.
> 
> I've been having a hard time getting the error lately (not encountered in
> the last two days with a kernel 3.17-rc4). I'll go back to a newer kernel
> and I'll see if the Packet0 bug still happens as often as before.
> 
> About the SSH connection, that could be possible if needed in time.

Well, at last, I've been able to hit the error with a 3.17-rc4 and something.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141013/30196cde/attachment.html>


[Linaro-mm-sig] [RFC 2/4] cenalloc: Constraint-Enabled Allocation helpers for dma-buf

2014-10-13 Thread Laura Abbott
On 10/10/2014 1:07 PM, Sumit Semwal wrote:
> Devices sharing buffers using dma-buf could benefit from sharing their
> constraints via struct device, and dma-buf framework would manage the
> common constraints for all attached devices per buffer.
>
> With that information, we could have a 'generic' allocator helper in
> the form of a central dma-buf exporter, which can create dma-bufs, and
> allocate backing storage at the time of first call to
> dma_buf_map_attachment.
>
> This allocation would utilise the constraint-mask by matching it to
> the right allocator from a pool of allocators, and then allocating
> buffer backing storage from this allocator.
>
> The pool of allocators could be platform-dependent, allowing for
> platforms to hide the specifics of these allocators from the devices
> that access the dma-buf buffers.
>
> A sample sequence could be:
> - get handle to cenalloc_device,
> - create a dmabuf using cenalloc_buffer_create;
> - use this dmabuf to attach each device, which has its constraints
> set in the constraints mask (dev->dma_params->access_constraints_mask)
>- at each dma_buf_attach() call, dma-buf will check to see if the 
> constraint
>  mask for the device requesting attachment is compatible with the 
> constraints
>  of devices already attached to the dma-buf; returns an error if it isn't.
> - after all devices have attached, the first call to dma_buf_map_attachment()
>will allocate the backing storage for the buffer.
> - follow the dma-buf api for map / unmap etc usage.
> - detach all attachments,
> - call cenalloc_buffer_free to free the buffer if refcount reaches zero;
>
> ** IMPORTANT**
> This mechanism of delayed allocation based on constraint-enablement will work
> *ONLY IF* the first map_attachment() call is made AFTER all attach() calls are
> done.
>

My first instinct is 'I wonder which drivers will call map_attachment at
the wrong time and screw things up'. Are there any plans for
synchronization and/or debugging output to catch drivers violating this
requirement?

[...]
> +int cenalloc_phys(struct dma_buf *dmabuf,
> +  phys_addr_t *addr, size_t *len)
> +{
> + struct cenalloc_buffer *buffer;
> + int ret;
> +
> + if (is_cenalloc_buffer(dmabuf))
> + buffer = (struct cenalloc_buffer *)dmabuf->priv;
> + else
> + return -EINVAL;
> +
> + if (!buffer->allocator->ops->phys) {
> + pr_err("%s: cenalloc_phys is not implemented by this 
> allocator.\n",
> +__func__);
> + return -ENODEV;
> + }
> + mutex_lock(>lock);
> + ret = buffer->allocator->ops->phys(buffer->allocator, buffer, addr,
> + len);
> + mutex_lock(>lock);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(cenalloc_phys);
> +

The .phys operation makes it difficult to have drivers which can
handle both contiguous and non contiguous memory (too much special
casing). Any chance we could drop this API and just have drivers
treat an sg_table with 1 entry as contiguous memory?

Thanks,
Laura

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


[Linaro-mm-sig] [RFC 1/4] dma-buf: Add constraints sharing information

2014-10-13 Thread Laura Abbott
On 10/11/2014 11:55 AM, Daniel Vetter wrote:
> On Sat, Oct 11, 2014 at 01:37:55AM +0530, Sumit Semwal wrote:
>> At present, struct device lacks a mechanism of exposing memory
>> access constraints for the device.
>>
>> Consequently, there is also no mechanism to share these constraints
>> while sharing buffers using dma-buf.
>>
>> If we add support for sharing such constraints, we could use that
>> to try to collect requirements of different buffer-sharing devices
>> to allocate buffers from a pool that satisfies requirements of all
>> such devices.
>>
>> This is an attempt to add this support; at the moment, only a bitmask
>> is added, but if post discussion, we realise we need more information,
>> we could always extend the definition of constraint.
>>
>> A new dma-buf op is also added, to allow exporters to interpret or decide
>> on constraint-masks on their own. A default implementation is provided to
>> just AND (&) all the constraint-masks.
>>
>> What constitutes a constraint-mask could be left for interpretation on a
>> per-platform basis, while defining some common masks.
>>
>> Signed-off-by: Sumit Semwal 
>> Cc: linux-kernel at vger.kernel.org
>> Cc: Greg Kroah-Hartman 
>> Cc: linux-media at vger.kernel.org
>> Cc: dri-devel at lists.freedesktop.org
>> Cc: linaro-mm-sig at lists.linaro.org
>
> Just a few high-level comments, I'm between conference travel but
> hopefully I can discuss this a bit at plumbers next week.
>
> - I agree that for the insane specific cases we need something opaque like
>the access constraints mask you propose here. But for the normal case I
>think the existing dma constraints in dma_params would go a long way,
>and I think we should look at Rob's RFC from aeons ago to solve those:
>
>https://lkml.org/lkml/2012/7/19/285
>
>With this we should be able to cover the allocation constraints of 90%
>of all cases hopefully.
>
> - I'm not sure whether an opaque bitmask is good enough really, I suspect
>that we also need various priorities between different allocators. With
>the option that some allocators are flat-out incompatible.
>

 From my experience with Ion, the bitmask is okay if you have only a few
types but as soon as there are multiple regions it gets complicated and
when you start adding in priority via id it really gets unwieldy.

Thanks,
Laura


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


[Linaro-mm-sig] [RFC 0/4] dma-buf Constraints-Enabled Allocation helpers

2014-10-13 Thread Laura Abbott
On 10/10/2014 1:07 PM, Sumit Semwal wrote:
> Hi,
>
> Why:
> 
>   While sharing buffers using dma-buf, currently there's no mechanism to let
> devices share their memory access constraints with each other to allow for
> delayed allocation of backing storage.
>
> This RFC attempts to introduce the idea of memory constraints of a device,
> and how these constraints can be shared and used to help allocate buffers that
> can satisfy requirements of all devices attached to a particular dma-buf.
>
> How:
> 
>   A constraints_mask is added to dma_parms of the device, and at the time of
> each device attachment to a dma-buf, the dma-buf uses this constraints_mask
> to calculate the access_mask for the dma-buf.
>
> Allocators can be defined for each of these constraints_masks, and then helper
> functions can be used to allocate the backing storage from the matching
> allocator satisfying the constraints of all devices interested.
>
> A new miscdevice, /dev/cenalloc [1] is created, which acts as the dma-buf
> exporter to make this transparent to the devices.
>
> More details in the patch description of "cenalloc: Constraint-Enabled
> Allocation helpers for dma-buf".
>
>
> At present, the constraint_mask is only a bitmask, but it should be possible 
> to
> change it to a struct and adapt the constraint_mask calculation accordingly,
> based on discussion.
>
>
> Important requirement:
> ==
>   Of course, delayed allocation can only work if all participating devices
> will wait for other devices to have 'attached' before mapping the buffer
> for the first time.
>
> As of now, users of dma-buf(drm prime, v4l2 etc) call the attach() and then
> map_attachment() almost immediately after it. This would need to be changed if
> they were to benefit from constraints.
>
>
> What 'cenalloc' is not:
> ===
> - not 'general' allocator helpers - useful only for constraints-enabled
>devices that share buffers with others using dma-buf.
> - not a replacement for existing allocation mechanisms inside various
>subsystems; merely a possible alternative.
> - no page-migration - it would be very complementary to the delayed allocation
> suggested here.
>
> TODOs:
> ==
> - demonstration test cases
> - vma helpers for allocators
> - more sample allocators
> - userspace ioctl (It should be a simple one, and we have one ready, but 
> wanted
> to agree on the kernel side of things first)
>
>

I'm interested to see the userspace ioctl. The mask based approach of
Ion does not scale well to a userspace ABI so I'm curious if cenalloc
does better.

Thanks,
Laura

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation