Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c859074e authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Ben Skeggs
Browse files

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: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent c072470f
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -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);
	}

@@ -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;
}

@@ -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));
	}

@@ -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) {