diff options
author | Dave Airlie <airlied@redhat.com> | 2017-01-08 18:13:20 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-01-08 18:13:26 -0500 |
commit | 6906407eeb690ed31b183a38ae10db2907cc3a58 (patch) | |
tree | f31d9bdd67bd74523e3dd5ac9e89490ec68361fd | |
parent | 90e5d2d45776451e58989361a182c067008d5941 (diff) | |
parent | a6cb3b864b21b7345f824a4faa12b723c8aaf099 (diff) |
Merge branch 'msm-fixes-4.10' of git://people.freedesktop.org/~robclark/linux into drm-fixes
A few fixes for 4.10.. the first fixes a long-standing logic bug, that
by luck (ie. size of packets written into RB for a submit) wasn't hit
on a3xx/a4xx but was causing intermittent GPU lockups on a5xx. And a
couple other robustness issues that Jordan noticed.
* 'msm-fixes-4.10' of git://people.freedesktop.org/~robclark/linux:
drm/msm: Verify that MSM_SUBMIT_BO_FLAGS are set
drm/msm: Put back the vaddr in submit_reloc()
drm/msm: Ensure that the hardware write pointer is valid
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem_submit.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_ringbuffer.c | 3 |
3 files changed, 21 insertions, 9 deletions
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index a18126150e11..14ff87686a36 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c | |||
@@ -213,7 +213,14 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, | |||
213 | void adreno_flush(struct msm_gpu *gpu) | 213 | void adreno_flush(struct msm_gpu *gpu) |
214 | { | 214 | { |
215 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | 215 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
216 | uint32_t wptr = get_wptr(gpu->rb); | 216 | uint32_t wptr; |
217 | |||
218 | /* | ||
219 | * Mask wptr value that we calculate to fit in the HW range. This is | ||
220 | * to account for the possibility that the last command fit exactly into | ||
221 | * the ringbuffer and rb->next hasn't wrapped to zero yet | ||
222 | */ | ||
223 | wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1); | ||
217 | 224 | ||
218 | /* ensure writes to ringbuffer have hit system memory: */ | 225 | /* ensure writes to ringbuffer have hit system memory: */ |
219 | mb(); | 226 | mb(); |
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 166e84e4f0d4..489676568a10 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c | |||
@@ -106,7 +106,8 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, | |||
106 | pagefault_disable(); | 106 | pagefault_disable(); |
107 | } | 107 | } |
108 | 108 | ||
109 | if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) { | 109 | if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) || |
110 | !(submit_bo.flags & MSM_SUBMIT_BO_FLAGS)) { | ||
110 | DRM_ERROR("invalid flags: %x\n", submit_bo.flags); | 111 | DRM_ERROR("invalid flags: %x\n", submit_bo.flags); |
111 | ret = -EINVAL; | 112 | ret = -EINVAL; |
112 | goto out_unlock; | 113 | goto out_unlock; |
@@ -290,7 +291,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob | |||
290 | { | 291 | { |
291 | uint32_t i, last_offset = 0; | 292 | uint32_t i, last_offset = 0; |
292 | uint32_t *ptr; | 293 | uint32_t *ptr; |
293 | int ret; | 294 | int ret = 0; |
294 | 295 | ||
295 | if (offset % 4) { | 296 | if (offset % 4) { |
296 | DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset); | 297 | DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset); |
@@ -318,12 +319,13 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob | |||
318 | 319 | ||
319 | ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc)); | 320 | ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc)); |
320 | if (ret) | 321 | if (ret) |
321 | return -EFAULT; | 322 | goto out; |
322 | 323 | ||
323 | if (submit_reloc.submit_offset % 4) { | 324 | if (submit_reloc.submit_offset % 4) { |
324 | DRM_ERROR("non-aligned reloc offset: %u\n", | 325 | DRM_ERROR("non-aligned reloc offset: %u\n", |
325 | submit_reloc.submit_offset); | 326 | submit_reloc.submit_offset); |
326 | return -EINVAL; | 327 | ret = -EINVAL; |
328 | goto out; | ||
327 | } | 329 | } |
328 | 330 | ||
329 | /* offset in dwords: */ | 331 | /* offset in dwords: */ |
@@ -332,12 +334,13 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob | |||
332 | if ((off >= (obj->base.size / 4)) || | 334 | if ((off >= (obj->base.size / 4)) || |
333 | (off < last_offset)) { | 335 | (off < last_offset)) { |
334 | DRM_ERROR("invalid offset %u at reloc %u\n", off, i); | 336 | DRM_ERROR("invalid offset %u at reloc %u\n", off, i); |
335 | return -EINVAL; | 337 | ret = -EINVAL; |
338 | goto out; | ||
336 | } | 339 | } |
337 | 340 | ||
338 | ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid); | 341 | ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid); |
339 | if (ret) | 342 | if (ret) |
340 | return ret; | 343 | goto out; |
341 | 344 | ||
342 | if (valid) | 345 | if (valid) |
343 | continue; | 346 | continue; |
@@ -354,9 +357,10 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob | |||
354 | last_offset = off; | 357 | last_offset = off; |
355 | } | 358 | } |
356 | 359 | ||
360 | out: | ||
357 | msm_gem_put_vaddr_locked(&obj->base); | 361 | msm_gem_put_vaddr_locked(&obj->base); |
358 | 362 | ||
359 | return 0; | 363 | return ret; |
360 | } | 364 | } |
361 | 365 | ||
362 | static void submit_cleanup(struct msm_gem_submit *submit) | 366 | static void submit_cleanup(struct msm_gem_submit *submit) |
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index f326cf6a32e6..67b34e069abf 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c | |||
@@ -23,7 +23,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size) | |||
23 | struct msm_ringbuffer *ring; | 23 | struct msm_ringbuffer *ring; |
24 | int ret; | 24 | int ret; |
25 | 25 | ||
26 | size = ALIGN(size, 4); /* size should be dword aligned */ | 26 | if (WARN_ON(!is_power_of_2(size))) |
27 | return ERR_PTR(-EINVAL); | ||
27 | 28 | ||
28 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 29 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
29 | if (!ring) { | 30 | if (!ring) { |