Skip to content

Commit

Permalink
drm/nouveau: fix command submission to use vmalloc for big allocations
Browse files Browse the repository at this point in the history
I was getting a order 4 allocation failure from kmalloc when testing some
game after a few days uptime with some suspend/resumes.

For big allocations vmalloc should be used instead.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Maarten Lankhorst authored and Ben Skeggs committed Sep 4, 2013
1 parent c072470 commit c859074
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions drivers/gpu/drm/nouveau/nouveau_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,18 +579,31 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
return 0;
}

static inline void
u_free(void *addr)
{
if (!is_vmalloc_addr(addr))
kfree(addr);
else
vfree(addr);
}

static inline void *
u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
{
void *mem;
void __user *userptr = (void __force __user *)(uintptr_t)user;

mem = kmalloc(nmemb * size, GFP_KERNEL);
size *= nmemb;

mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
if (!mem)
mem = vmalloc(size);
if (!mem)
return ERR_PTR(-ENOMEM);

if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) {
kfree(mem);
if (DRM_COPY_FROM_USER(mem, userptr, size)) {
u_free(mem);
return ERR_PTR(-EFAULT);
}

Expand Down Expand Up @@ -676,7 +689,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
}

kfree(reloc);
u_free(reloc);
return ret;
}

Expand Down Expand Up @@ -738,7 +751,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,

bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
if (IS_ERR(bo)) {
kfree(push);
u_free(push);
return nouveau_abi16_put(abi16, PTR_ERR(bo));
}

Expand Down Expand Up @@ -849,8 +862,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
nouveau_fence_unref(&fence);

out_prevalid:
kfree(bo);
kfree(push);
u_free(bo);
u_free(push);

out_next:
if (chan->dma.ib_max) {
Expand Down

0 comments on commit c859074

Please sign in to comment.