mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 09:18:04 +02:00
nouveau: handle realloc failure inside cli_kref_set
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11477
Fixes: 821f4c8d99 ("nouveau: import libdrm_nouveau")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30374>
This commit is contained in:
parent
f8bf9f07b6
commit
801078cbf8
2 changed files with 29 additions and 9 deletions
|
|
@ -94,7 +94,8 @@ PUSH_KICK(struct nouveau_pushbuf *push)
|
|||
{
|
||||
struct nouveau_pushbuf_priv *ppush = push->user_priv;
|
||||
simple_mtx_lock(&ppush->screen->fence.lock);
|
||||
nouveau_pushbuf_kick(push);
|
||||
int ASSERTED ret = nouveau_pushbuf_kick(push);
|
||||
assert(!ret);
|
||||
simple_mtx_unlock(&ppush->screen->fence.lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -848,13 +848,18 @@ cli_kref_get(struct nouveau_client *client, struct nouveau_bo *bo)
|
|||
return kref;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
cli_kref_set(struct nouveau_client *client, struct nouveau_bo *bo,
|
||||
struct drm_nouveau_gem_pushbuf_bo *kref, struct nouveau_pushbuf *push)
|
||||
{
|
||||
struct nouveau_client_priv *pcli = nouveau_client(client);
|
||||
if (pcli->kref_nr <= bo->handle) {
|
||||
pcli->kref = realloc(pcli->kref, sizeof(*pcli->kref) * bo->handle * 2);
|
||||
void *new_ptr = realloc(pcli->kref, sizeof(*pcli->kref) * bo->handle * 2);
|
||||
if (!new_ptr) {
|
||||
err("Failed to realloc memory, expect faulty rendering.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
pcli->kref = new_ptr;
|
||||
while (pcli->kref_nr < bo->handle * 2) {
|
||||
pcli->kref[pcli->kref_nr].kref = NULL;
|
||||
pcli->kref[pcli->kref_nr].push = NULL;
|
||||
|
|
@ -863,6 +868,7 @@ cli_kref_set(struct nouveau_client *client, struct nouveau_bo *bo,
|
|||
}
|
||||
pcli->kref[bo->handle].kref = kref;
|
||||
pcli->kref[bo->handle].push = push;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1203,7 +1209,9 @@ pushbuf_flush(struct nouveau_pushbuf *push)
|
|||
kref = krec->buffer;
|
||||
for (i = 0; i < krec->nr_buffer; i++, kref++) {
|
||||
struct nouveau_bo *bo = (void *)(unsigned long)kref->user_priv;
|
||||
cli_kref_set(push->client, bo, NULL, NULL);
|
||||
ret = cli_kref_set(push->client, bo, NULL, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
nouveau_bo_ref(NULL, &bo);
|
||||
}
|
||||
|
||||
|
|
@ -1299,6 +1307,7 @@ pushbuf_kref(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags
|
|||
struct nouveau_pushbuf *fpush;
|
||||
struct drm_nouveau_gem_pushbuf_bo *kref;
|
||||
uint32_t domains, domains_wr, domains_rd;
|
||||
int ret;
|
||||
|
||||
domains = 0;
|
||||
if (flags & NOUVEAU_BO_VRAM)
|
||||
|
|
@ -1354,7 +1363,9 @@ pushbuf_kref(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t flags
|
|||
else
|
||||
kref->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
|
||||
|
||||
cli_kref_set(push->client, bo, kref, push);
|
||||
ret = cli_kref_set(push->client, bo, kref, push);
|
||||
if (ret)
|
||||
return NULL;
|
||||
p_atomic_inc(&nouveau_bo(bo)->refcnt);
|
||||
}
|
||||
|
||||
|
|
@ -1401,22 +1412,26 @@ pushbuf_krel(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
|
|||
return reloc;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
pushbuf_refn_fail(struct nouveau_pushbuf *push, int sref, int srel)
|
||||
{
|
||||
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
|
||||
struct nouveau_pushbuf_krec *krec = nvpb->krec;
|
||||
struct drm_nouveau_gem_pushbuf_bo *kref;
|
||||
int ret;
|
||||
|
||||
kref = krec->buffer + sref;
|
||||
while (krec->nr_buffer-- > sref) {
|
||||
struct nouveau_bo *bo = (void *)(unsigned long)kref->user_priv;
|
||||
cli_kref_set(push->client, bo, NULL, NULL);
|
||||
ret = cli_kref_set(push->client, bo, NULL, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
nouveau_bo_ref(NULL, &bo);
|
||||
kref++;
|
||||
}
|
||||
krec->nr_buffer = sref;
|
||||
krec->nr_reloc = srel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1438,7 +1453,9 @@ pushbuf_refn(struct nouveau_pushbuf *push, bool retry,
|
|||
}
|
||||
|
||||
if (ret) {
|
||||
pushbuf_refn_fail(push, sref, krec->nr_reloc);
|
||||
ret = pushbuf_refn_fail(push, sref, krec->nr_reloc);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (retry) {
|
||||
pushbuf_flush(push);
|
||||
nouveau_pushbuf_space(push, 0, 0, 0);
|
||||
|
|
@ -1489,7 +1506,9 @@ pushbuf_validate(struct nouveau_pushbuf *push, bool retry)
|
|||
list_inithead(&bctx->pending);
|
||||
|
||||
if (ret) {
|
||||
pushbuf_refn_fail(push, sref, srel);
|
||||
ret = pushbuf_refn_fail(push, sref, srel);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (retry) {
|
||||
pushbuf_flush(push);
|
||||
return pushbuf_validate(push, false);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue