Commit 90d6db16 authored by Ilia Mirkin's avatar Ilia Mirkin Committed by Ben Skeggs

drm/nouveau/falcon: use vmalloc to create firwmare copies

Some firmware images may be large (64K), so using kmalloc memory is
inappropriate for them. Use vmalloc instead, to avoid high-order
allocation failures.
Signed-off-by: default avatarIlia Mirkin <imirkin@alum.mit.edu>
Cc: stable@vger.kernel.org
parent d96bf437
...@@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data) ...@@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data)
nv_wr32(falcon, falcon->addr + addr, data); nv_wr32(falcon, falcon->addr + addr, data);
} }
static void *
vmemdup(const void *src, size_t len)
{
void *p = vmalloc(len);
if (p)
memcpy(p, src, len);
return p;
}
int int
_nouveau_falcon_init(struct nouveau_object *object) _nouveau_falcon_init(struct nouveau_object *object)
{ {
...@@ -111,7 +121,7 @@ _nouveau_falcon_init(struct nouveau_object *object) ...@@ -111,7 +121,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
ret = request_firmware(&fw, name, &device->pdev->dev); ret = request_firmware(&fw, name, &device->pdev->dev);
if (ret == 0) { if (ret == 0) {
falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL); falcon->code.data = vmemdup(fw->data, fw->size);
falcon->code.size = fw->size; falcon->code.size = fw->size;
falcon->data.data = NULL; falcon->data.data = NULL;
falcon->data.size = 0; falcon->data.size = 0;
...@@ -134,7 +144,7 @@ _nouveau_falcon_init(struct nouveau_object *object) ...@@ -134,7 +144,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
return ret; return ret;
} }
falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL); falcon->data.data = vmemdup(fw->data, fw->size);
falcon->data.size = fw->size; falcon->data.size = fw->size;
release_firmware(fw); release_firmware(fw);
if (!falcon->data.data) if (!falcon->data.data)
...@@ -149,7 +159,7 @@ _nouveau_falcon_init(struct nouveau_object *object) ...@@ -149,7 +159,7 @@ _nouveau_falcon_init(struct nouveau_object *object)
return ret; return ret;
} }
falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL); falcon->code.data = vmemdup(fw->data, fw->size);
falcon->code.size = fw->size; falcon->code.size = fw->size;
release_firmware(fw); release_firmware(fw);
if (!falcon->code.data) if (!falcon->code.data)
...@@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend) ...@@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)
if (!suspend) { if (!suspend) {
nouveau_gpuobj_ref(NULL, &falcon->core); nouveau_gpuobj_ref(NULL, &falcon->core);
if (falcon->external) { if (falcon->external) {
kfree(falcon->data.data); vfree(falcon->data.data);
kfree(falcon->code.data); vfree(falcon->code.data);
falcon->code.data = NULL; falcon->code.data = NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment