diff options
author | Dave Airlie <airlied@redhat.com> | 2013-09-19 19:06:48 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-09-19 19:06:48 -0400 |
commit | 6ddf2ed6e00396883b3123032ccb4416205aac7c (patch) | |
tree | aa544e6288bfc4c9aba53df49be798bb2226ffe8 /drivers/gpu/drm/msm/msm_gpu.c | |
parent | 9808cc946943e4c260ff270f8b2e7884dd6968f8 (diff) | |
parent | 7e60353a1f5335ecd63b1c54897c2aa75874aaee (diff) |
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
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gpu.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index e1e1ec9321ff..3bab937965d1 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c | |||
@@ -29,13 +29,14 @@ | |||
29 | static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) | 29 | static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) |
30 | { | 30 | { |
31 | struct drm_device *dev = gpu->dev; | 31 | struct drm_device *dev = gpu->dev; |
32 | struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; | 32 | struct kgsl_device_platform_data *pdata; |
33 | 33 | ||
34 | if (!pdev) { | 34 | if (!pdev) { |
35 | dev_err(dev->dev, "could not find dtv pdata\n"); | 35 | dev_err(dev->dev, "could not find dtv pdata\n"); |
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | 38 | ||
39 | pdata = pdev->dev.platform_data; | ||
39 | if (pdata->bus_scale_table) { | 40 | if (pdata->bus_scale_table) { |
40 | gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table); | 41 | gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table); |
41 | DBG("bus scale client: %08x", gpu->bsc); | 42 | DBG("bus scale client: %08x", gpu->bsc); |
@@ -230,6 +231,8 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu) | |||
230 | static void hangcheck_handler(unsigned long data) | 231 | static void hangcheck_handler(unsigned long data) |
231 | { | 232 | { |
232 | struct msm_gpu *gpu = (struct msm_gpu *)data; | 233 | struct msm_gpu *gpu = (struct msm_gpu *)data; |
234 | struct drm_device *dev = gpu->dev; | ||
235 | struct msm_drm_private *priv = dev->dev_private; | ||
233 | uint32_t fence = gpu->funcs->last_fence(gpu); | 236 | uint32_t fence = gpu->funcs->last_fence(gpu); |
234 | 237 | ||
235 | if (fence != gpu->hangcheck_fence) { | 238 | if (fence != gpu->hangcheck_fence) { |
@@ -237,14 +240,22 @@ static void hangcheck_handler(unsigned long data) | |||
237 | gpu->hangcheck_fence = fence; | 240 | gpu->hangcheck_fence = fence; |
238 | } else if (fence < gpu->submitted_fence) { | 241 | } else if (fence < gpu->submitted_fence) { |
239 | /* no progress and not done.. hung! */ | 242 | /* no progress and not done.. hung! */ |
240 | struct msm_drm_private *priv = gpu->dev->dev_private; | ||
241 | gpu->hangcheck_fence = fence; | 243 | gpu->hangcheck_fence = fence; |
244 | dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n", | ||
245 | gpu->name); | ||
246 | dev_err(dev->dev, "%s: completed fence: %u\n", | ||
247 | gpu->name, fence); | ||
248 | dev_err(dev->dev, "%s: submitted fence: %u\n", | ||
249 | gpu->name, gpu->submitted_fence); | ||
242 | queue_work(priv->wq, &gpu->recover_work); | 250 | queue_work(priv->wq, &gpu->recover_work); |
243 | } | 251 | } |
244 | 252 | ||
245 | /* if still more pending work, reset the hangcheck timer: */ | 253 | /* if still more pending work, reset the hangcheck timer: */ |
246 | if (gpu->submitted_fence > gpu->hangcheck_fence) | 254 | if (gpu->submitted_fence > gpu->hangcheck_fence) |
247 | hangcheck_timer_reset(gpu); | 255 | hangcheck_timer_reset(gpu); |
256 | |||
257 | /* workaround for missing irq: */ | ||
258 | queue_work(priv->wq, &gpu->retire_work); | ||
248 | } | 259 | } |
249 | 260 | ||
250 | /* | 261 | /* |
@@ -265,7 +276,8 @@ static void retire_worker(struct work_struct *work) | |||
265 | obj = list_first_entry(&gpu->active_list, | 276 | obj = list_first_entry(&gpu->active_list, |
266 | struct msm_gem_object, mm_list); | 277 | struct msm_gem_object, mm_list); |
267 | 278 | ||
268 | if (obj->fence <= fence) { | 279 | if ((obj->read_fence <= fence) && |
280 | (obj->write_fence <= fence)) { | ||
269 | /* move to inactive: */ | 281 | /* move to inactive: */ |
270 | msm_gem_move_to_inactive(&obj->base); | 282 | msm_gem_move_to_inactive(&obj->base); |
271 | msm_gem_put_iova(&obj->base, gpu->id); | 283 | msm_gem_put_iova(&obj->base, gpu->id); |
@@ -321,7 +333,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, | |||
321 | submit->gpu->id, &iova); | 333 | submit->gpu->id, &iova); |
322 | } | 334 | } |
323 | 335 | ||
324 | msm_gem_move_to_active(&msm_obj->base, gpu, submit->fence); | 336 | if (submit->bos[i].flags & MSM_SUBMIT_BO_READ) |
337 | msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence); | ||
338 | |||
339 | if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) | ||
340 | msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); | ||
325 | } | 341 | } |
326 | hangcheck_timer_reset(gpu); | 342 | hangcheck_timer_reset(gpu); |
327 | mutex_unlock(&dev->struct_mutex); | 343 | mutex_unlock(&dev->struct_mutex); |