This patch fixes a race condition that causes a use-after-free during
amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits
are requested and the second one finishes before the first. Essentially,
this bug occurs when the following sequence of events happens:
1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is
deferred to the workqueue.
2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is
deferred to the workqueue.
3. Commit #2 starts before …
[View More]commit #1, dm_state #1 is used in the
commit_tail and commit #2 completes, freeing dm_state #1.
4. Commit #1 starts after commit #2 completes, uses the freed dm_state
1 and dereferences a freelist pointer while setting the context.
Since this bug has only been spotted with fast commits, this patch fixes
the bug by clearing the dm_state instead of using the old dc_state for
fast updates. In addition, since dm_state is only used for its dc_state
and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found,
removing the dm_state should not have any consequences in fast updates.
This use-after-free bug has existed for a while now, but only caused a
noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate
freelist pointer to middle of object") moving the freelist pointer from
dm_state->base (which was unused) to dm_state->context (which is
dereferenced).
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383
Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast updates")
Reported-by: Duncan <1i5t5.duncan(a)cox.net>
Signed-off-by: Mazin Rezk <mnrzk(a)protonmail.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++++++++++++++-----
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 86ffa0c2880f..710edc70e37e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
* the same resource. If we have a new DC context as part of
* the DM atomic state from validation we need to free it and
* retain the existing one instead.
+ *
+ * Furthermore, since the DM atomic state only contains the DC
+ * context and can safely be annulled, we can free the state
+ * and clear the associated private object now to free
+ * some memory and avoid a possible use-after-free later.
*/
- struct dm_atomic_state *new_dm_state, *old_dm_state;
- new_dm_state = dm_atomic_get_new_state(state);
- old_dm_state = dm_atomic_get_old_state(state);
+ for (i = 0; i < state->num_private_objs; i++) {
+ struct drm_private_obj *obj = state->private_objs[i].ptr;
- if (new_dm_state && old_dm_state) {
- if (new_dm_state->context)
- dc_release_state(new_dm_state->context);
+ if (obj->funcs == adev->dm.atomic_obj.funcs) {
+ int j = state->num_private_objs-1;
- new_dm_state->context = old_dm_state->context;
+ dm_atomic_destroy_state(obj,
+ state->private_objs[i].state);
+
+ /* If i is not at the end of the array then the
+ * last element needs to be moved to where i was
+ * before the array can safely be truncated.
+ */
+ if (i != j)
+ state->private_objs[i] =
+ state->private_objs[j];
- if (old_dm_state->context)
- dc_retain_state(old_dm_state->context);
+ state->private_objs[j].ptr = NULL;
+ state->private_objs[j].state = NULL;
+ state->private_objs[j].old_state = NULL;
+ state->private_objs[j].new_state = NULL;
+
+ state->num_private_objs = j;
+ break;
+ }
}
}
--
2.27.0
[View Less]
Hi Dave,
This time around:
* A bunch more a650/a640 (sm8150/sm8250) display and GPU enablement
and fixes
* Enable dpu dither block for 6bpc panels
* dpu suspend fixes
* dpu fix for cursor on 2nd display
* dsi/mdp5 enablement for sdm630/sdm636/sdm660
* gpu opp/bw scaling for a6xx
For the last part, there is one OPP patch that is ack'd by the OPP
maintainer to land thru the drm tree (since we are currently it's
sole user, and this avoids having to send a 2nd late PR).
I also regenerated the …
[View More]register headers, which accounts for a good
bit of the size this time, because we hadn't re-synced the register
headers since the early days of a6xx bringup.
The following changes since commit b3a9e3b9622ae10064826dccb4f7a52bd88c7407:
Linux 5.8-rc1 (2020-06-14 12:45:04 -0700)
are available in the Git repository at:
https://gitlab.freedesktop.org/drm/msm.git drm-msm-next-2020-07-29
for you to fetch changes up to 00be2abf1413bec4f4f83681cf5dcee7afbd9b4b:
drm/msm: use kthread_create_worker instead of kthread_run
(2020-07-26 11:35:45 -0700)
----------------------------------------------------------------
Akhil P Oommen (2):
drm/msm: Fix a null pointer access in msm_gem_shrinker_count()
drm: msm: a6xx: fix gpu failure after system resume
Bernard (1):
drm/msm: use kthread_create_worker instead of kthread_run
Bernard Zhao (1):
drm/msm: fix potential memleak in error branch
Chen Tao (1):
drm/msm/dpu: fix error return code in dpu_encoder_init
Eric Anholt (4):
drm/msm: Fix address space size after refactor.
drm/msm: Fix setup of a6xx create_address_space.
drm/msm: Garbage collect unused resource _len fields.
drm/msm: Quiet error during failure in optional resource mappings.
John Stultz (1):
drm/msm: Fix 0xfffflub in "Refactor address space initialization"
Jonathan Marek (16):
drm/msm: fix unbalanced pm_runtime_enable in adreno_gpu_{init, cleanup}
drm/msm: reset devfreq freq_table/max_state before devfreq_add_device
drm/msm: handle for EPROBE_DEFER for of_icc_get
drm/msm/a6xx: fix crashstate capture for A650
drm/msm/a6xx: add build_bw_table for A640/A650
drm/msm/a6xx: set ubwc config for A640 and A650
drm/msm/dpu: use right setup_blend_config for sm8150 and sm8250
drm/msm/dpu: update UBWC config for sm8150 and sm8250
drm/msm/dpu: move some sspp caps to dpu_caps
drm/msm/dpu: don't use INTF_INPUT_CTRL feature on sdm845
drm/msm/dpu: set missing flush bits for INTF_2 and INTF_3
drm/msm/dpu: intf timing path for displayport
drm/msm/dpu: add SM8150 to hw catalog
drm/msm/dpu: add SM8250 to hw catalog
drm/msm/a6xx: hwcg tables in gpulist
drm/msm/a6xx: add A640/A650 hwcg
Jordan Crouse (1):
drm/msm: Fix up the rest of the messed up address sizes
Kalyan Thota (4):
drm/msm/dpu: request for display color blocks based on hw catalog entry
drm/msm/dpu: ensure device suspend happens during PM sleep
drm/msm/dpu: enumerate second cursor pipe for external interface
drm/msm/dpu: add support for dither block in display
Konrad Dybcio (4):
drm/msm/dsi: Add phy configuration for SDM630/636/660
drm/msm/mdp5: Add MDP5 configuration for SDM630
drm/msm/dsi: Add DSI configuration for SDM660
drm/msm/mdp5: Add MDP5 configuration for SDM636/660
Krishna Manikandan (1):
drm/msm/dpu: allow initialization of encoder locks during encoder init
Rajendra Nayak (2):
drm/msm/dpu: Use OPP API to set clk/perf state
drm/msm: dsi: Use OPP API to set clk/perf state
Rob Clark (5):
drm/msm/adreno: fix gpu probe if no interconnect-names
drm/msm: ratelimit crtc event overflow error
drm/msm/dpu: fix/enable 6bpc dither with split-lm
drm/msm: sync generated headers
drm/msm/adreno: un-open-code some packets
Sharat Masetty (3):
dt-bindings: drm/msm/gpu: Document gpu opp table
drm: msm: a6xx: send opp instead of a frequency
drm: msm: a6xx: use dev_pm_opp_set_bw to scale DDR
Sibi Sankar (1):
OPP: Add and export helper to set bandwidth
.../devicetree/bindings/display/msm/dsi.txt | 1 +
.../devicetree/bindings/display/msm/gpu.txt | 28 +
drivers/gpu/drm/msm/adreno/a2xx.xml.h | 1102 +++++-
drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 2 +-
drivers/gpu/drm/msm/adreno/a3xx.xml.h | 102 +-
drivers/gpu/drm/msm/adreno/a4xx.xml.h | 125 +-
drivers/gpu/drm/msm/adreno/a5xx.xml.h | 403 ++-
drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 5 +-
drivers/gpu/drm/msm/adreno/a6xx.xml.h | 3624 ++++++++++++++++----
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 128 +-
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 5 +
drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h | 147 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 193 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 2 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 25 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h | 12 +-
drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 74 +
drivers/gpu/drm/msm/adreno/adreno_common.xml.h | 230 +-
drivers/gpu/drm/msm/adreno/adreno_device.c | 3 +
drivers/gpu/drm/msm/adreno/adreno_gpu.c | 72 +-
drivers/gpu/drm/msm/adreno/adreno_gpu.h | 8 +
drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h | 933 ++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 4 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 67 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 297 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 48 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 20 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 29 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 5 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 62 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 28 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 16 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 18 -
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h | 7 -
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 56 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 5 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 84 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 6 +-
drivers/gpu/drm/msm/disp/mdp4/mdp4.xml.h | 26 +-
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 2 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5.xml.h | 26 +-
drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 198 ++
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 +-
drivers/gpu/drm/msm/disp/mdp_common.xml.h | 26 +-
drivers/gpu/drm/msm/dsi/dsi.c | 2 +
drivers/gpu/drm/msm/dsi/dsi.xml.h | 230 +-
drivers/gpu/drm/msm/dsi/dsi_cfg.c | 21 +
drivers/gpu/drm/msm/dsi/dsi_cfg.h | 1 +
drivers/gpu/drm/msm/dsi/dsi_host.c | 41 +-
drivers/gpu/drm/msm/dsi/mmss_cc.xml.h | 26 +-
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 2 +
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 +
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 18 +
drivers/gpu/drm/msm/dsi/sfpb.xml.h | 26 +-
drivers/gpu/drm/msm/edp/edp.xml.h | 26 +-
drivers/gpu/drm/msm/hdmi/hdmi.xml.h | 26 +-
drivers/gpu/drm/msm/hdmi/qfprom.xml.h | 26 +-
drivers/gpu/drm/msm/msm_drv.c | 107 +-
drivers/gpu/drm/msm/msm_drv.h | 5 +-
drivers/gpu/drm/msm/msm_gem.c | 36 +-
drivers/gpu/drm/msm/msm_gpu.c | 7 +-
drivers/gpu/drm/msm/msm_gpu.h | 3 +-
drivers/gpu/drm/msm/msm_submitqueue.c | 4 +-
drivers/opp/core.c | 31 +
include/linux/pm_opp.h | 6 +
67 files changed, 7277 insertions(+), 1629 deletions(-)
[View Less]
On Wed, Jul 29, 2020 at 2:19 AM Christoph Hellwig <hch(a)lst.de> wrote:
>
> On Tue, Jul 28, 2020 at 02:24:51PM -0400, Jim Quinlan wrote:
> > I started using devm_kcalloc() but at least two reviewers convinced me
> > to just use kcalloc(). In addition, when I was using devm_kcalloc()
> > it was awkward because 'dev' is not available to this function.
> >
> > It comes down to whether unbind/binding the device N times is actually
> > a reasonable …
[View More]usage. As for my experience I've seen two cases: (1) my
> > overnight "bind/unbind the PCIe RC driver" script, and we have a
> > customer who does an unbind/bind as a hail mary to bring back life to
> > their dead EP device. If the latter case happens repeatedly, there
> > are bigger problems.
>
> We can't just leak the allocations. Do you have a pointer to the
> arguments against managed resources? I'm generally not a huge fan
> of the managed resources, but for a case like this they actually seem
> useful. If we don't use the managed resources we'll at leat need
> to explicitly free the resources when freeing the device.
Actually, there were no arguments for using an unmanaged kcalloc, just
comments [1], [2]. When it was rightly suggested to have 'dev'
dropped from of_dma_range() [3], I submitted v6 to accomplish this.
But now of_dma_range() would call kcalloc(), and then
of_dma_configure() was required to "dup" the result, requiring a
devm_kcalloc(), memcpy(), and kfree(). This was awkward, so
considering [1], [2], I dropped the devm_kcalloc() and submitted v7.
So I can easily revert to the awkward code of v6. But I'm hoping you
have a more elegant solution :-)
Thanks,
Jim
[1]
[v6, Andy Shevchenko]
> + /* We want the offset map to be device-managed, so alloc & copy */
> + dev->dma_range_map = devm_kcalloc(dev, num_ranges + 1, sizeof(*r),
> + GFP_KERNEL);
The question is how many times per device lifetime this can be called?
[2]
[v2, Andy Shevchenko]
> + r = devm_kzalloc(dev, r_size, GFP_KERNEL);
devm_?!
Looking at r_size it should be rather kcalloc().
[3]
[v3, Nicolas Saenz Julienne]
> I agree with you. The reason I needed a "struct device *" in the call is
> because I wanted to make sure the memory that is alloc'd belongs to the
> device that needs it. If I do a regular kzalloc(), this memory will become
> a leak once someone starts unbinding/binding their device. Also, in all
> uses of of_dma_rtange() -- there is only one -- a dev is required as one
> can't attach an offset map to NULL.
>
> I do see that there are a number of functions in drivers/of/*.c that
> take 'struct device *dev' as an argument so there is precedent for
> something like this. Regardless, I need an owner to the memory I
> alloc().
I understand the need for dev to be around, devm_*() is key. But also it's
important to keep the functions on purpose. And if of_dma_get_range() starts
setting ranges it calls, for the very least, for a function rename. Although
I'd rather split the parsing and setting of ranges as mentioned earlier. That
said, I get that's a more drastic move.
[View Less]
The current vgacon's scroll up implementation uses a circural buffer
in vgacon_scrollback_cur. It always advances tail to prepare it for the
next write and caps it to zero if the next ->vc_size_row bytes won't fit.
But when we change the VT size (e.g. by VT_RESIZE) in the meantime, the new
line might not fit to the end of the scrollback buffer in the next
attempt to scroll. This leads to various crashes as
vgacon_scrollback_update writes out of the buffer:
BUG: unable to handle page fault …
[View More]for address: ffffc900001752a0
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
RIP: 0010:mutex_unlock+0x13/0x30
...
Call Trace:
n_tty_write+0x1a0/0x4d0
tty_write+0x1a0/0x2e0
Or to KASAN reports:
BUG: KASAN: slab-out-of-bounds in vgacon_scroll+0x57a/0x8ed
So check whether the line fits in the buffer and wrap if needed. Do it
before the loop as console_sem is held and ->vc_size_row cannot change
during the execution of vgacon_scrollback_cur. If it does change, we
need to ensure it does not change elsewhere, not here.
Also, we do not split the write of a line into chunks as that would
break the consumers of the buffer. They expect ->cnt, ->tail and ->size
to be in harmony and advanced by ->vc_size_row.
I found few reports of this in the past, some with patches included,
some even 2 years old:
https://lore.kernel.org/lkml/CAEAjamsJnG-=TSOwgRbbb3B9Z-PA63oWmNPoKYWQ=Z=+X…https://lore.kernel.org/lkml/1589336932-35508-1-git-send-email-yangyinglian…
This fixes CVE-2020-14331.
Big thanks to guys mentioned in the Reported-and-debugged-by lines below
who actually found the root cause.
Signed-off-by: Jiri Slaby <jslaby(a)suse.cz>
Reported-and-debugged-by: 张云海 <zhangyunhai(a)nsfocus.com>
Reported-and-debugged-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reported-by: Kyungtae Kim <kt0755(a)gmail.com>
Fixes: 15bdab959c9b ([PATCH] vgacon: Add support for soft scrollback)
Cc: Linus Torvalds <torvalds(a)linux-foundation.org>
Cc: Greg KH <greg(a)kroah.com>
Cc: Solar Designer <solar(a)openwall.com>
Cc: "Srivatsa S. Bhat" <srivatsa(a)csail.mit.edu>
Cc: Anthony Liguori <aliguori(a)amazon.com>
Cc: Security Officers <security(a)kernel.org>
Cc: linux-distros(a)vs.openwall.org
Cc: Yang Yingliang <yangyingliang(a)huawei.com>
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie(a)samsung.com>
Cc: dri-devel(a)lists.freedesktop.org
Cc: linux-fbdev(a)vger.kernel.org
---
drivers/video/console/vgacon.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index f0f3d573f848..13194bb246f8 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -250,6 +250,11 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
p = (void *) (c->vc_origin + t * c->vc_size_row);
+ /* vc_size_row might have changed by VT_RESIZE in the meantime */
+ if ((vgacon_scrollback_cur->tail + c->vc_size_row) >=
+ vgacon_scrollback_cur->size)
+ vgacon_scrollback_cur->tail = 0;
+
while (count--) {
scr_memcpyw(vgacon_scrollback_cur->data +
vgacon_scrollback_cur->tail,
--
2.28.0
[View Less]
From: Dave Airlie <airlied(a)redhat.com>
Drop the WARN_ON and consolidate the two paths into one.
Use the consolidate slowpath in the execbuf utils code.
Signed-off-by: Dave Airlie <airlied(a)redhat.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 +-
drivers/gpu/drm/ttm/ttm_execbuf_util.c | 12 +--
include/drm/ttm/ttm_bo_driver.h | 91 ++++------------------
3 files changed, 20 insertions(+), 85 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/…
[View More]amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index afa5189dba7d..e01e8903741e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -160,7 +160,7 @@ static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr)
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
int r;
- r = __ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
+ r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS)
dev_err(adev->dev, "%p reserve failed\n", bo);
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index 1797f04c0534..8a8f1a6a83a6 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -93,7 +93,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
list_for_each_entry(entry, list, head) {
struct ttm_buffer_object *bo = entry->bo;
- ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket);
+ ret = ttm_bo_reserve(bo, intr, (ticket == NULL), ticket);
if (ret == -EALREADY && dups) {
struct ttm_validate_buffer *safe = entry;
entry = list_prev_entry(entry, head);
@@ -119,13 +119,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
ttm_eu_backoff_reservation_reverse(list, entry);
if (ret == -EDEADLK) {
- if (intr) {
- ret = dma_resv_lock_slow_interruptible(bo->base.resv,
- ticket);
- } else {
- dma_resv_lock_slow(bo->base.resv, ticket);
- ret = 0;
- }
+ ret = ttm_bo_reserve_slowpath(bo, intr, ticket);
}
if (!ret && entry->num_shared)
@@ -133,8 +127,6 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
entry->num_shared);
if (unlikely(ret != 0)) {
- if (ret == -EINTR)
- ret = -ERESTARTSYS;
if (ticket) {
ww_acquire_done(ticket);
ww_acquire_fini(ticket);
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 5a37f1cc057e..bfa9d146d3d4 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -597,29 +597,30 @@ int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible);
void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
/**
- * __ttm_bo_reserve:
+ * ttm_bo_reserve:
*
* @bo: A pointer to a struct ttm_buffer_object.
* @interruptible: Sleep interruptible if waiting.
* @no_wait: Don't sleep while trying to reserve, rather return -EBUSY.
* @ticket: ticket used to acquire the ww_mutex.
*
- * Will not remove reserved buffers from the lru lists.
- * Otherwise identical to ttm_bo_reserve.
+ * Locks a buffer object for validation. (Or prevents other processes from
+ * locking it for validation), while taking a number of measures to prevent
+ * deadlocks.
*
* Returns:
* -EDEADLK: The reservation may cause a deadlock.
* Release all buffer reservations, wait for @bo to become unreserved and
- * try again. (only if use_sequence == 1).
+ * try again.
* -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
* a signal. Release all buffer reservations and return to user-space.
* -EBUSY: The function needed to sleep, but @no_wait was true
* -EALREADY: Bo already reserved using @ticket. This error code will only
* be returned if @use_ticket is set to true.
*/
-static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo,
- bool interruptible, bool no_wait,
- struct ww_acquire_ctx *ticket)
+static inline int ttm_bo_reserve(struct ttm_buffer_object *bo,
+ bool interruptible, bool no_wait,
+ struct ww_acquire_ctx *ticket)
{
int ret = 0;
@@ -641,59 +642,6 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo,
return ret;
}
-/**
- * ttm_bo_reserve:
- *
- * @bo: A pointer to a struct ttm_buffer_object.
- * @interruptible: Sleep interruptible if waiting.
- * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY.
- * @ticket: ticket used to acquire the ww_mutex.
- *
- * Locks a buffer object for validation. (Or prevents other processes from
- * locking it for validation) and removes it from lru lists, while taking
- * a number of measures to prevent deadlocks.
- *
- * Deadlocks may occur when two processes try to reserve multiple buffers in
- * different order, either by will or as a result of a buffer being evicted
- * to make room for a buffer already reserved. (Buffers are reserved before
- * they are evicted). The following algorithm prevents such deadlocks from
- * occurring:
- * Processes attempting to reserve multiple buffers other than for eviction,
- * (typically execbuf), should first obtain a unique 32-bit
- * validation sequence number,
- * and call this function with @use_ticket == 1 and @ticket->stamp == the unique
- * sequence number. If upon call of this function, the buffer object is already
- * reserved, the validation sequence is checked against the validation
- * sequence of the process currently reserving the buffer,
- * and if the current validation sequence is greater than that of the process
- * holding the reservation, the function returns -EDEADLK. Otherwise it sleeps
- * waiting for the buffer to become unreserved, after which it retries
- * reserving.
- * The caller should, when receiving an -EDEADLK error
- * release all its buffer reservations, wait for @bo to become unreserved, and
- * then rerun the validation with the same validation sequence. This procedure
- * will always guarantee that the process with the lowest validation sequence
- * will eventually succeed, preventing both deadlocks and starvation.
- *
- * Returns:
- * -EDEADLK: The reservation may cause a deadlock.
- * Release all buffer reservations, wait for @bo to become unreserved and
- * try again. (only if use_sequence == 1).
- * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
- * a signal. Release all buffer reservations and return to user-space.
- * -EBUSY: The function needed to sleep, but @no_wait was true
- * -EALREADY: Bo already reserved using @ticket. This error code will only
- * be returned if @use_ticket is set to true.
- */
-static inline int ttm_bo_reserve(struct ttm_buffer_object *bo,
- bool interruptible, bool no_wait,
- struct ww_acquire_ctx *ticket)
-{
- WARN_ON(!kref_read(&bo->kref));
-
- return __ttm_bo_reserve(bo, interruptible, no_wait, ticket);
-}
-
/**
* ttm_bo_reserve_slowpath:
* @bo: A pointer to a struct ttm_buffer_object.
@@ -708,20 +656,15 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
bool interruptible,
struct ww_acquire_ctx *ticket)
{
- int ret = 0;
-
- WARN_ON(!kref_read(&bo->kref));
-
- if (interruptible)
- ret = dma_resv_lock_slow_interruptible(bo->base.resv,
- ticket);
- else
- dma_resv_lock_slow(bo->base.resv, ticket);
-
- if (ret == -EINTR)
- ret = -ERESTARTSYS;
-
- return ret;
+ if (interruptible) {
+ int ret = dma_resv_lock_slow_interruptible(bo->base.resv,
+ ticket);
+ if (ret == -EINTR)
+ ret = -ERESTARTSYS;
+ return ret;
+ }
+ dma_resv_lock_slow(bo->base.resv, ticket);
+ return 0;
}
/**
--
2.26.2
[View Less]
The function mcde_display_send_one_frame() has a historical
name that stems from being implemented when the driver
only supported single frame updates.
Rename it mcde_start_flow() so that it reflects the current
usage.
Reviewed-by: Stephan Gerhold <stephan(a)gerhold.net>
Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org>
---
ChangeLog v1->v2:
- Collect Stephan's review tag.
---
drivers/gpu/drm/mcde/mcde_display.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
…
[View More]
diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c
index 4d2290f88edb..363fa5ca4b45 100644
--- a/drivers/gpu/drm/mcde/mcde_display.c
+++ b/drivers/gpu/drm/mcde/mcde_display.c
@@ -968,7 +968,7 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe)
dev_info(drm->dev, "MCDE display is disabled\n");
}
-static void mcde_display_send_one_frame(struct mcde *mcde)
+static void mcde_start_flow(struct mcde *mcde)
{
/* Request a TE ACK */
if (mcde->te_sync)
@@ -1066,7 +1066,7 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe,
* is not active yet.
*/
if (mcde->flow_active == 0)
- mcde_display_send_one_frame(mcde);
+ mcde_start_flow(mcde);
}
dev_info_once(mcde->dev, "sent first display update\n");
} else {
--
2.26.2
[View Less]