Message ID | 20201004192152.3298573-8-robdclark@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | drm/msm: de-struct_mutex-ification | expand |
On Sun, Oct 04, 2020 at 12:21:39PM -0700, Rob Clark wrote: > From: Rob Clark <robdclark@chromium.org> > > Before we remove dev->struct_mutex from the retire path, we have to deal > with the situation of a submit retiring before the submit ioctl returns. > > To deal with this, ring->submits will hold a reference to the submit, > which is dropped when the submit is retired. And the submit ioctl path > holds it's own ref, which it drops when it is done with the submit. > > Also, add to submit list *after* getting/pinning bo's, to prevent badness > in case the completed fence is corrupted, and retire_worker mistakenly > believes the submit is done too early. Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> > Signed-off-by: Rob Clark <robdclark@chromium.org> > --- > drivers/gpu/drm/msm/msm_drv.h | 1 - > drivers/gpu/drm/msm/msm_gem.h | 13 +++++++++++++ > drivers/gpu/drm/msm/msm_gem_submit.c | 12 ++++++------ > drivers/gpu/drm/msm/msm_gpu.c | 21 ++++++++++++++++----- > 4 files changed, 35 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h > index 50978e5db376..535f9e718e2d 100644 > --- a/drivers/gpu/drm/msm/msm_drv.h > +++ b/drivers/gpu/drm/msm/msm_drv.h > @@ -277,7 +277,6 @@ void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu); > > bool msm_use_mmu(struct drm_device *dev); > > -void msm_gem_submit_free(struct msm_gem_submit *submit); > int msm_ioctl_gem_submit(struct drm_device *dev, void *data, > struct drm_file *file); > > diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h > index a1bf741b9b89..e05b1530aca6 100644 > --- a/drivers/gpu/drm/msm/msm_gem.h > +++ b/drivers/gpu/drm/msm/msm_gem.h > @@ -136,6 +136,7 @@ void msm_gem_free_work(struct work_struct *work); > * lasts for the duration of the submit-ioctl. > */ > struct msm_gem_submit { > + struct kref ref; > struct drm_device *dev; > struct msm_gpu *gpu; > struct msm_gem_address_space *aspace; > @@ -169,6 +170,18 @@ struct msm_gem_submit { > } bos[]; > }; > > +void __msm_gem_submit_destroy(struct kref *kref); > + > +static inline void msm_gem_submit_get(struct msm_gem_submit *submit) > +{ > + kref_get(&submit->ref); > +} > + > +static inline void msm_gem_submit_put(struct msm_gem_submit *submit) > +{ > + kref_put(&submit->ref, __msm_gem_submit_destroy); > +} > + > /* helper to determine of a buffer in submit should be dumped, used for both > * devcoredump and debugfs cmdstream dumping: > */ > diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c > index e1d1f005b3d4..7d653bdc92dc 100644 > --- a/drivers/gpu/drm/msm/msm_gem_submit.c > +++ b/drivers/gpu/drm/msm/msm_gem_submit.c > @@ -42,6 +42,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, > if (!submit) > return NULL; > > + kref_init(&submit->ref); > submit->dev = dev; > submit->aspace = queue->ctx->aspace; > submit->gpu = gpu; > @@ -60,12 +61,12 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, > return submit; > } > > -void msm_gem_submit_free(struct msm_gem_submit *submit) > +void __msm_gem_submit_destroy(struct kref *kref) > { > + struct msm_gem_submit *submit = > + container_of(kref, struct msm_gem_submit, ref); > + > dma_fence_put(submit->fence); > - spin_lock(&submit->ring->submit_lock); > - list_del(&submit->node); > - spin_unlock(&submit->ring->submit_lock); > put_pid(submit->pid); > msm_submitqueue_put(submit->queue); > > @@ -805,8 +806,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, > submit_cleanup(submit); > if (has_ww_ticket) > ww_acquire_fini(&submit->ticket); > - if (ret) > - msm_gem_submit_free(submit); > + msm_gem_submit_put(submit); > out_unlock: > if (ret && (out_fence_fd >= 0)) > put_unused_fd(out_fence_fd); > diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c > index 8d1e254f964a..fd3fc6f36ab1 100644 > --- a/drivers/gpu/drm/msm/msm_gpu.c > +++ b/drivers/gpu/drm/msm/msm_gpu.c > @@ -712,7 +712,12 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring, > > pm_runtime_mark_last_busy(&gpu->pdev->dev); > pm_runtime_put_autosuspend(&gpu->pdev->dev); > - msm_gem_submit_free(submit); > + > + spin_lock(&ring->submit_lock); > + list_del(&submit->node); > + spin_unlock(&ring->submit_lock); > + > + msm_gem_submit_put(submit); > } > > static void retire_submits(struct msm_gpu *gpu) > @@ -786,10 +791,6 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) > > submit->seqno = ++ring->seqno; > > - spin_lock(&ring->submit_lock); > - list_add_tail(&submit->node, &ring->submits); > - spin_unlock(&ring->submit_lock); > - > msm_rd_dump_submit(priv->rd, submit, NULL); > > update_sw_cntrs(gpu); > @@ -816,6 +817,16 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) > msm_gem_active_get(drm_obj, gpu); > } > > + /* > + * ring->submits holds a ref to the submit, to deal with the case > + * that a submit completes before msm_ioctl_gem_submit() returns. > + */ > + msm_gem_submit_get(submit); > + > + spin_lock(&ring->submit_lock); > + list_add_tail(&submit->node, &ring->submits); > + spin_unlock(&ring->submit_lock); > + > gpu->funcs->submit(gpu, submit); > priv->lastctx = submit->queue->ctx; > > -- > 2.26.2 > > _______________________________________________ > Freedreno mailing list > Freedreno@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/freedreno
On Mon, Oct 5, 2020 at 6:56 AM Daniel Vetter <daniel@ffwll.ch> wrote: > > On Sun, Oct 04, 2020 at 12:21:39PM -0700, Rob Clark wrote: > > From: Rob Clark <robdclark@chromium.org> > > > > Before we remove dev->struct_mutex from the retire path, we have to deal > > with the situation of a submit retiring before the submit ioctl returns. > > > > To deal with this, ring->submits will hold a reference to the submit, > > which is dropped when the submit is retired. And the submit ioctl path > > holds it's own ref, which it drops when it is done with the submit. > > > > Also, add to submit list *after* getting/pinning bo's, to prevent badness > > in case the completed fence is corrupted, and retire_worker mistakenly > > believes the submit is done too early. > > > > Signed-off-by: Rob Clark <robdclark@chromium.org> > > Why not embed the dma_fence instead of pointer and use that refcount? i915 > does that, and imo kinda makes sense instead of more refcounted things. > But might not make sense for msm. I guess that might work.. the one thing I'd be concerned about is that the submit (indirectly) holds reference to the file ctx, so userspace keeping around a fence fd by mistake could keep a set of pgtables live unnecessarily.. I suppose we could re-work where we drop that reference. six of one, half-dozen of the other, I guess BR, -R > -Daniel > > > --- > > drivers/gpu/drm/msm/msm_drv.h | 1 - > > drivers/gpu/drm/msm/msm_gem.h | 13 +++++++++++++ > > drivers/gpu/drm/msm/msm_gem_submit.c | 12 ++++++------ > > drivers/gpu/drm/msm/msm_gpu.c | 21 ++++++++++++++++----- > > 4 files changed, 35 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h > > index 50978e5db376..535f9e718e2d 100644 > > --- a/drivers/gpu/drm/msm/msm_drv.h > > +++ b/drivers/gpu/drm/msm/msm_drv.h > > @@ -277,7 +277,6 @@ void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu); > > > > bool msm_use_mmu(struct drm_device *dev); > > > > -void msm_gem_submit_free(struct msm_gem_submit *submit); > > int msm_ioctl_gem_submit(struct drm_device *dev, void *data, > > struct drm_file *file); > > > > diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h > > index a1bf741b9b89..e05b1530aca6 100644 > > --- a/drivers/gpu/drm/msm/msm_gem.h > > +++ b/drivers/gpu/drm/msm/msm_gem.h > > @@ -136,6 +136,7 @@ void msm_gem_free_work(struct work_struct *work); > > * lasts for the duration of the submit-ioctl. > > */ > > struct msm_gem_submit { > > + struct kref ref; > > struct drm_device *dev; > > struct msm_gpu *gpu; > > struct msm_gem_address_space *aspace; > > @@ -169,6 +170,18 @@ struct msm_gem_submit { > > } bos[]; > > }; > > > > +void __msm_gem_submit_destroy(struct kref *kref); > > + > > +static inline void msm_gem_submit_get(struct msm_gem_submit *submit) > > +{ > > + kref_get(&submit->ref); > > +} > > + > > +static inline void msm_gem_submit_put(struct msm_gem_submit *submit) > > +{ > > + kref_put(&submit->ref, __msm_gem_submit_destroy); > > +} > > + > > /* helper to determine of a buffer in submit should be dumped, used for both > > * devcoredump and debugfs cmdstream dumping: > > */ > > diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c > > index e1d1f005b3d4..7d653bdc92dc 100644 > > --- a/drivers/gpu/drm/msm/msm_gem_submit.c > > +++ b/drivers/gpu/drm/msm/msm_gem_submit.c > > @@ -42,6 +42,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, > > if (!submit) > > return NULL; > > > > + kref_init(&submit->ref); > > submit->dev = dev; > > submit->aspace = queue->ctx->aspace; > > submit->gpu = gpu; > > @@ -60,12 +61,12 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, > > return submit; > > } > > > > -void msm_gem_submit_free(struct msm_gem_submit *submit) > > +void __msm_gem_submit_destroy(struct kref *kref) > > { > > + struct msm_gem_submit *submit = > > + container_of(kref, struct msm_gem_submit, ref); > > + > > dma_fence_put(submit->fence); > > - spin_lock(&submit->ring->submit_lock); > > - list_del(&submit->node); > > - spin_unlock(&submit->ring->submit_lock); > > put_pid(submit->pid); > > msm_submitqueue_put(submit->queue); > > > > @@ -805,8 +806,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, > > submit_cleanup(submit); > > if (has_ww_ticket) > > ww_acquire_fini(&submit->ticket); > > - if (ret) > > - msm_gem_submit_free(submit); > > + msm_gem_submit_put(submit); > > out_unlock: > > if (ret && (out_fence_fd >= 0)) > > put_unused_fd(out_fence_fd); > > diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c > > index 8d1e254f964a..fd3fc6f36ab1 100644 > > --- a/drivers/gpu/drm/msm/msm_gpu.c > > +++ b/drivers/gpu/drm/msm/msm_gpu.c > > @@ -712,7 +712,12 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring, > > > > pm_runtime_mark_last_busy(&gpu->pdev->dev); > > pm_runtime_put_autosuspend(&gpu->pdev->dev); > > - msm_gem_submit_free(submit); > > + > > + spin_lock(&ring->submit_lock); > > + list_del(&submit->node); > > + spin_unlock(&ring->submit_lock); > > + > > + msm_gem_submit_put(submit); > > } > > > > static void retire_submits(struct msm_gpu *gpu) > > @@ -786,10 +791,6 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) > > > > submit->seqno = ++ring->seqno; > > > > - spin_lock(&ring->submit_lock); > > - list_add_tail(&submit->node, &ring->submits); > > - spin_unlock(&ring->submit_lock); > > - > > msm_rd_dump_submit(priv->rd, submit, NULL); > > > > update_sw_cntrs(gpu); > > @@ -816,6 +817,16 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) > > msm_gem_active_get(drm_obj, gpu); > > } > > > > + /* > > + * ring->submits holds a ref to the submit, to deal with the case > > + * that a submit completes before msm_ioctl_gem_submit() returns. > > + */ > > + msm_gem_submit_get(submit); > > + > > + spin_lock(&ring->submit_lock); > > + list_add_tail(&submit->node, &ring->submits); > > + spin_unlock(&ring->submit_lock); > > + > > gpu->funcs->submit(gpu, submit); > > priv->lastctx = submit->queue->ctx; > > > > -- > > 2.26.2 > > > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 50978e5db376..535f9e718e2d 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -277,7 +277,6 @@ void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu); bool msm_use_mmu(struct drm_device *dev); -void msm_gem_submit_free(struct msm_gem_submit *submit); int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index a1bf741b9b89..e05b1530aca6 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -136,6 +136,7 @@ void msm_gem_free_work(struct work_struct *work); * lasts for the duration of the submit-ioctl. */ struct msm_gem_submit { + struct kref ref; struct drm_device *dev; struct msm_gpu *gpu; struct msm_gem_address_space *aspace; @@ -169,6 +170,18 @@ struct msm_gem_submit { } bos[]; }; +void __msm_gem_submit_destroy(struct kref *kref); + +static inline void msm_gem_submit_get(struct msm_gem_submit *submit) +{ + kref_get(&submit->ref); +} + +static inline void msm_gem_submit_put(struct msm_gem_submit *submit) +{ + kref_put(&submit->ref, __msm_gem_submit_destroy); +} + /* helper to determine of a buffer in submit should be dumped, used for both * devcoredump and debugfs cmdstream dumping: */ diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index e1d1f005b3d4..7d653bdc92dc 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -42,6 +42,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, if (!submit) return NULL; + kref_init(&submit->ref); submit->dev = dev; submit->aspace = queue->ctx->aspace; submit->gpu = gpu; @@ -60,12 +61,12 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, return submit; } -void msm_gem_submit_free(struct msm_gem_submit *submit) +void __msm_gem_submit_destroy(struct kref *kref) { + struct msm_gem_submit *submit = + container_of(kref, struct msm_gem_submit, ref); + dma_fence_put(submit->fence); - spin_lock(&submit->ring->submit_lock); - list_del(&submit->node); - spin_unlock(&submit->ring->submit_lock); put_pid(submit->pid); msm_submitqueue_put(submit->queue); @@ -805,8 +806,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, submit_cleanup(submit); if (has_ww_ticket) ww_acquire_fini(&submit->ticket); - if (ret) - msm_gem_submit_free(submit); + msm_gem_submit_put(submit); out_unlock: if (ret && (out_fence_fd >= 0)) put_unused_fd(out_fence_fd); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 8d1e254f964a..fd3fc6f36ab1 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -712,7 +712,12 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring, pm_runtime_mark_last_busy(&gpu->pdev->dev); pm_runtime_put_autosuspend(&gpu->pdev->dev); - msm_gem_submit_free(submit); + + spin_lock(&ring->submit_lock); + list_del(&submit->node); + spin_unlock(&ring->submit_lock); + + msm_gem_submit_put(submit); } static void retire_submits(struct msm_gpu *gpu) @@ -786,10 +791,6 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) submit->seqno = ++ring->seqno; - spin_lock(&ring->submit_lock); - list_add_tail(&submit->node, &ring->submits); - spin_unlock(&ring->submit_lock); - msm_rd_dump_submit(priv->rd, submit, NULL); update_sw_cntrs(gpu); @@ -816,6 +817,16 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) msm_gem_active_get(drm_obj, gpu); } + /* + * ring->submits holds a ref to the submit, to deal with the case + * that a submit completes before msm_ioctl_gem_submit() returns. + */ + msm_gem_submit_get(submit); + + spin_lock(&ring->submit_lock); + list_add_tail(&submit->node, &ring->submits); + spin_unlock(&ring->submit_lock); + gpu->funcs->submit(gpu, submit); priv->lastctx = submit->queue->ctx;