Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ddf2ed6 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'msm-fixes-3.12' of git://people.freedesktop.org/~robclark/linux into drm-fixes

A couple small msm fixes.  Plus drop of set_need_resched().

* 'msm-fixes-3.12' of git://people.freedesktop.org/~robclark/linux:
  drm/msm: drop unnecessary set_need_resched()
  drm/msm: fix potential NULL pointer dereference
  drm/msm: workaround for missing irq
  drm/msm: return -EBUSY if bo still active
  drm/msm: fix return value check in ERR_PTR()
  drm/msm: fix cmdstream size check
  drm/msm: hangcheck harder
  drm/msm: handle read vs write fences
parents 9808cc94 7e60353a
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -124,6 +124,8 @@ void adreno_recover(struct msm_gpu *gpu)

	/* reset completed fence seqno, just discard anything pending: */
	adreno_gpu->memptrs->fence = gpu->submitted_fence;
	adreno_gpu->memptrs->rptr  = 0;
	adreno_gpu->memptrs->wptr  = 0;

	gpu->funcs->pm_resume(gpu);
	ret = gpu->funcs->hw_init(gpu);
@@ -229,7 +231,7 @@ void adreno_idle(struct msm_gpu *gpu)
			return;
	} while(time_before(jiffies, t));

	DRM_ERROR("timeout waiting for %s to drain ringbuffer!\n", gpu->name);
	DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);

	/* TODO maybe we need to reset GPU here to recover from hang? */
}
@@ -256,11 +258,17 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
{
	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
	uint32_t freedwords;
	unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT;
	do {
		uint32_t size = gpu->rb->size / 4;
		uint32_t wptr = get_wptr(gpu->rb);
		uint32_t rptr = adreno_gpu->memptrs->rptr;
		freedwords = (rptr + (size - 1) - wptr) % size;

		if (time_after(jiffies, t)) {
			DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
			break;
		}
	} while(freedwords < ndwords);
}

+33 −17
Original line number Diff line number Diff line
@@ -499,10 +499,24 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
		struct timespec *timeout)
{
	struct msm_drm_private *priv = dev->dev_private;
	int ret;

	if (!priv->gpu)
		return 0;

	if (fence > priv->gpu->submitted_fence) {
		DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
				fence, priv->gpu->submitted_fence);
		return -EINVAL;
	}

	if (!timeout) {
		/* no-wait: */
		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
	} else {
		unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
		unsigned long start_jiffies = jiffies;
		unsigned long remaining_jiffies;
	int ret;

		if (time_after(start_jiffies, timeout_jiffies))
			remaining_jiffies = 0;
@@ -510,8 +524,9 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
			remaining_jiffies = timeout_jiffies - start_jiffies;

		ret = wait_event_interruptible_timeout(priv->fence_event,
			priv->completed_fence >= fence,
				fence_completed(dev, fence),
				remaining_jiffies);

		if (ret == 0) {
			DBG("timeout waiting for fence: %u (completed: %u)",
					fence, priv->completed_fence);
@@ -519,6 +534,7 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
		} else if (ret != -ERESTARTSYS) {
			ret = 0;
		}
	}

	return ret;
}
+7 −1
Original line number Diff line number Diff line
@@ -153,7 +153,7 @@ void *msm_gem_vaddr(struct drm_gem_object *obj);
int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
		struct work_struct *work);
void msm_gem_move_to_active(struct drm_gem_object *obj,
		struct msm_gpu *gpu, uint32_t fence);
		struct msm_gpu *gpu, bool write, uint32_t fence);
void msm_gem_move_to_inactive(struct drm_gem_object *obj);
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
		struct timespec *timeout);
@@ -191,6 +191,12 @@ u32 msm_readl(const void __iomem *addr);
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)

static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
{
	struct msm_drm_private *priv = dev->dev_private;
	return priv->completed_fence >= fence;
}

static inline int align_pitch(int width, int bpp)
{
	int bytespp = (bpp + 7) / 8;
+24 −10
Original line number Diff line number Diff line
@@ -40,9 +40,9 @@ static struct page **get_pages(struct drm_gem_object *obj)
		}

		msm_obj->sgt = drm_prime_pages_to_sg(p, npages);
		if (!msm_obj->sgt) {
		if (IS_ERR(msm_obj->sgt)) {
			dev_err(dev->dev, "failed to allocate sgt\n");
			return ERR_PTR(-ENOMEM);
			return ERR_CAST(msm_obj->sgt);
		}

		msm_obj->pages = p;
@@ -159,7 +159,6 @@ int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
out:
	switch (ret) {
	case -EAGAIN:
		set_need_resched();
	case 0:
	case -ERESTARTSYS:
	case -EINTR:
@@ -393,11 +392,14 @@ int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
}

void msm_gem_move_to_active(struct drm_gem_object *obj,
		struct msm_gpu *gpu, uint32_t fence)
		struct msm_gpu *gpu, bool write, uint32_t fence)
{
	struct msm_gem_object *msm_obj = to_msm_bo(obj);
	msm_obj->gpu = gpu;
	msm_obj->fence = fence;
	if (write)
		msm_obj->write_fence = fence;
	else
		msm_obj->read_fence = fence;
	list_del_init(&msm_obj->mm_list);
	list_add_tail(&msm_obj->mm_list, &gpu->active_list);
}
@@ -411,7 +413,8 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
	WARN_ON(!mutex_is_locked(&dev->struct_mutex));

	msm_obj->gpu = NULL;
	msm_obj->fence = 0;
	msm_obj->read_fence = 0;
	msm_obj->write_fence = 0;
	list_del_init(&msm_obj->mm_list);
	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);

@@ -433,8 +436,18 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
	struct msm_gem_object *msm_obj = to_msm_bo(obj);
	int ret = 0;

	if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC))
		ret = msm_wait_fence_interruptable(dev, msm_obj->fence, timeout);
	if (is_active(msm_obj)) {
		uint32_t fence = 0;

		if (op & MSM_PREP_READ)
			fence = msm_obj->write_fence;
		if (op & MSM_PREP_WRITE)
			fence = max(fence, msm_obj->read_fence);
		if (op & MSM_PREP_NOSYNC)
			timeout = NULL;

		ret = msm_wait_fence_interruptable(dev, fence, timeout);
	}

	/* TODO cache maintenance */

@@ -455,9 +468,10 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
	uint64_t off = drm_vma_node_start(&obj->vma_node);

	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
	seq_printf(m, "%08x: %c(%d) %2d (%2d) %08llx %p %d\n",
	seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n",
			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
			msm_obj->fence, obj->name, obj->refcount.refcount.counter,
			msm_obj->read_fence, msm_obj->write_fence,
			obj->name, obj->refcount.refcount.counter,
			off, msm_obj->vaddr, obj->size);
}

+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ struct msm_gem_object {
	 */
	struct list_head mm_list;
	struct msm_gpu *gpu;     /* non-null if active */
	uint32_t fence;
	uint32_t read_fence, write_fence;

	/* Transiently in the process of submit ioctl, objects associated
	 * with the submit are on submit->bo_list.. this only lasts for
Loading