Skip to content

Commit c859074

Browse files
Maarten LankhorstBen Skeggs
authored andcommitted
drm/nouveau: fix command submission to use vmalloc for big allocations
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 <[email protected]> Signed-off-by: Ben Skeggs <[email protected]>
1 parent c072470 commit c859074

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

drivers/gpu/drm/nouveau/nouveau_gem.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -579,18 +579,31 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
579579
return 0;
580580
}
581581

582+
static inline void
583+
u_free(void *addr)
584+
{
585+
if (!is_vmalloc_addr(addr))
586+
kfree(addr);
587+
else
588+
vfree(addr);
589+
}
590+
582591
static inline void *
583592
u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
584593
{
585594
void *mem;
586595
void __user *userptr = (void __force __user *)(uintptr_t)user;
587596

588-
mem = kmalloc(nmemb * size, GFP_KERNEL);
597+
size *= nmemb;
598+
599+
mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
600+
if (!mem)
601+
mem = vmalloc(size);
589602
if (!mem)
590603
return ERR_PTR(-ENOMEM);
591604

592-
if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) {
593-
kfree(mem);
605+
if (DRM_COPY_FROM_USER(mem, userptr, size)) {
606+
u_free(mem);
594607
return ERR_PTR(-EFAULT);
595608
}
596609

@@ -676,7 +689,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
676689
nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
677690
}
678691

679-
kfree(reloc);
692+
u_free(reloc);
680693
return ret;
681694
}
682695

@@ -738,7 +751,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
738751

739752
bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
740753
if (IS_ERR(bo)) {
741-
kfree(push);
754+
u_free(push);
742755
return nouveau_abi16_put(abi16, PTR_ERR(bo));
743756
}
744757

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

851864
out_prevalid:
852-
kfree(bo);
853-
kfree(push);
865+
u_free(bo);
866+
u_free(push);
854867

855868
out_next:
856869
if (chan->dma.ib_max) {

0 commit comments

Comments
 (0)