diff options
| author | Takashi Iwai <tiwai@suse.de> | 2012-05-21 12:45:18 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2012-05-21 12:45:18 +0200 | 
| commit | 775b2449bdba7c97dda9f274c92bf7a83dac4142 (patch) | |
| tree | b4bee45c13762ea93642b1e38c62de454e51cf5d /drivers/gpu/drm/exynos/exynos_drm_gem.c | |
| parent | 21363cf0ca5c9c62e34e37422fb1d13d70d3de3c (diff) | |
| parent | 5fb86e5d4a951ddb0474cdfd809380c8e2a8d101 (diff) | |
| download | olio-linux-3.10-775b2449bdba7c97dda9f274c92bf7a83dac4142.tar.xz olio-linux-3.10-775b2449bdba7c97dda9f274c92bf7a83dac4142.zip  | |
Merge branch 'topic/asoc' into for-linus
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_gem.c')
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 79 | 
1 files changed, 42 insertions, 37 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index fa1aa94a3d8..1dffa8359f8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -56,9 +56,28 @@ static unsigned int convert_to_vm_err_msg(int msg)  	return out_msg;  } -static unsigned int mask_gem_flags(unsigned int flags) +static int check_gem_flags(unsigned int flags)  { -	return flags &= EXYNOS_BO_NONCONTIG; +	if (flags & ~(EXYNOS_BO_MASK)) { +		DRM_ERROR("invalid flags.\n"); +		return -EINVAL; +	} + +	return 0; +} + +static unsigned long roundup_gem_size(unsigned long size, unsigned int flags) +{ +	if (!IS_NONCONTIG_BUFFER(flags)) { +		if (size >= SZ_1M) +			return roundup(size, SECTION_SIZE); +		else if (size >= SZ_64K) +			return roundup(size, SZ_64K); +		else +			goto out; +	} +out: +	return roundup(size, PAGE_SIZE);  }  static struct page **exynos_gem_get_pages(struct drm_gem_object *obj, @@ -130,22 +149,12 @@ static int exynos_drm_gem_map_pages(struct drm_gem_object *obj,  	unsigned long pfn;  	if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { -		unsigned long usize = buf->size; -  		if (!buf->pages)  			return -EINTR; -		while (usize > 0) { -			pfn = page_to_pfn(buf->pages[page_offset++]); -			vm_insert_mixed(vma, f_vaddr, pfn); -			f_vaddr += PAGE_SIZE; -			usize -= PAGE_SIZE; -		} - -		return 0; -	} - -	pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset; +		pfn = page_to_pfn(buf->pages[page_offset++]); +	} else +		pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;  	return vm_insert_mixed(vma, f_vaddr, pfn);  } @@ -319,10 +328,17 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,  	struct exynos_drm_gem_buf *buf;  	int ret; -	size = roundup(size, PAGE_SIZE); -	DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size); +	if (!size) { +		DRM_ERROR("invalid size.\n"); +		return ERR_PTR(-EINVAL); +	} + +	size = roundup_gem_size(size, flags); +	DRM_DEBUG_KMS("%s\n", __FILE__); -	flags = mask_gem_flags(flags); +	ret = check_gem_flags(flags); +	if (ret) +		return ERR_PTR(ret);  	buf = exynos_drm_init_buf(dev, size);  	if (!buf) @@ -331,7 +347,7 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,  	exynos_gem_obj = exynos_drm_gem_init(dev, size);  	if (!exynos_gem_obj) {  		ret = -ENOMEM; -		goto err; +		goto err_fini_buf;  	}  	exynos_gem_obj->buffer = buf; @@ -347,18 +363,19 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,  		ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);  		if (ret < 0) {  			drm_gem_object_release(&exynos_gem_obj->base); -			goto err; +			goto err_fini_buf;  		}  	} else {  		ret = exynos_drm_alloc_buf(dev, buf, flags);  		if (ret < 0) {  			drm_gem_object_release(&exynos_gem_obj->base); -			goto err; +			goto err_fini_buf;  		}  	}  	return exynos_gem_obj; -err: + +err_fini_buf:  	exynos_drm_fini_buf(dev, buf);  	return ERR_PTR(ret);  } @@ -497,6 +514,8 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,  		if (!buffer->pages)  			return -EINVAL; +		vma->vm_flags |= VM_MIXEDMAP; +  		do {  			ret = vm_insert_page(vma, uaddr, buffer->pages[i++]);  			if (ret) { @@ -554,10 +573,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,  	obj->filp->f_op = &exynos_drm_gem_fops;  	obj->filp->private_data = obj; -	down_write(¤t->mm->mmap_sem); -	addr = do_mmap(obj->filp, 0, args->size, +	addr = vm_mmap(obj->filp, 0, args->size,  			PROT_READ | PROT_WRITE, MAP_SHARED, 0); -	up_write(¤t->mm->mmap_sem);  	drm_gem_object_unreference_unlocked(obj); @@ -685,7 +702,6 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,  int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  {  	struct drm_gem_object *obj = vma->vm_private_data; -	struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);  	struct drm_device *dev = obj->dev;  	unsigned long f_vaddr;  	pgoff_t page_offset; @@ -697,21 +713,10 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  	mutex_lock(&dev->struct_mutex); -	/* -	 * allocate all pages as desired size if user wants to allocate -	 * physically non-continuous memory. -	 */ -	if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) { -		ret = exynos_drm_gem_get_pages(obj); -		if (ret < 0) -			goto err; -	} -  	ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset);  	if (ret < 0)  		DRM_ERROR("failed to map pages.\n"); -err:  	mutex_unlock(&dev->struct_mutex);  	return convert_to_vm_err_msg(ret);  |