diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 487242fb3fdc..f32b71238c03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -579,18 +579,31 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, | |||
| 579 | return 0; | 579 | return 0; |
| 580 | } | 580 | } |
| 581 | 581 | ||
| 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 | |||
| 582 | static inline void * | 591 | static inline void * |
| 583 | u_memcpya(uint64_t user, unsigned nmemb, unsigned size) | 592 | u_memcpya(uint64_t user, unsigned nmemb, unsigned size) |
| 584 | { | 593 | { |
| 585 | void *mem; | 594 | void *mem; |
| 586 | void __user *userptr = (void __force __user *)(uintptr_t)user; | 595 | void __user *userptr = (void __force __user *)(uintptr_t)user; |
| 587 | 596 | ||
| 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); | ||
| 589 | if (!mem) | 602 | if (!mem) |
| 590 | return ERR_PTR(-ENOMEM); | 603 | return ERR_PTR(-ENOMEM); |
| 591 | 604 | ||
| 592 | if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) { | 605 | if (DRM_COPY_FROM_USER(mem, userptr, size)) { |
| 593 | kfree(mem); | 606 | u_free(mem); |
| 594 | return ERR_PTR(-EFAULT); | 607 | return ERR_PTR(-EFAULT); |
| 595 | } | 608 | } |
| 596 | 609 | ||
| @@ -676,7 +689,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
| 676 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); | 689 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); |
| 677 | } | 690 | } |
| 678 | 691 | ||
| 679 | kfree(reloc); | 692 | u_free(reloc); |
| 680 | return ret; | 693 | return ret; |
| 681 | } | 694 | } |
| 682 | 695 | ||
| @@ -738,7 +751,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
| 738 | 751 | ||
| 739 | bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); | 752 | bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); |
| 740 | if (IS_ERR(bo)) { | 753 | if (IS_ERR(bo)) { |
| 741 | kfree(push); | 754 | u_free(push); |
| 742 | return nouveau_abi16_put(abi16, PTR_ERR(bo)); | 755 | return nouveau_abi16_put(abi16, PTR_ERR(bo)); |
| 743 | } | 756 | } |
| 744 | 757 | ||
| @@ -849,8 +862,8 @@ out: | |||
| 849 | nouveau_fence_unref(&fence); | 862 | nouveau_fence_unref(&fence); |
| 850 | 863 | ||
| 851 | out_prevalid: | 864 | out_prevalid: |
| 852 | kfree(bo); | 865 | u_free(bo); |
| 853 | kfree(push); | 866 | u_free(push); |
| 854 | 867 | ||
| 855 | out_next: | 868 | out_next: |
| 856 | if (chan->dma.ib_max) { | 869 | if (chan->dma.ib_max) { |
