1 // SPDX-License-Identifier: GPL-2.0
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
9 #include <linux/shmem_fs.h>
13 static struct vkms_gem_object
*__vkms_gem_create(struct drm_device
*dev
,
16 struct vkms_gem_object
*obj
;
19 obj
= kzalloc(sizeof(*obj
), GFP_KERNEL
);
21 return ERR_PTR(-ENOMEM
);
23 size
= roundup(size
, PAGE_SIZE
);
24 ret
= drm_gem_object_init(dev
, &obj
->gem
, size
);
30 mutex_init(&obj
->pages_lock
);
35 void vkms_gem_free_object(struct drm_gem_object
*obj
)
37 struct vkms_gem_object
*gem
= container_of(obj
, struct vkms_gem_object
,
41 mutex_destroy(&gem
->pages_lock
);
42 drm_gem_object_release(obj
);
46 int vkms_gem_fault(struct vm_fault
*vmf
)
48 struct vm_area_struct
*vma
= vmf
->vma
;
49 struct vkms_gem_object
*obj
= vma
->vm_private_data
;
50 unsigned long vaddr
= vmf
->address
;
55 page_offset
= (vaddr
- vma
->vm_start
) >> PAGE_SHIFT
;
56 num_pages
= DIV_ROUND_UP(obj
->gem
.size
, PAGE_SIZE
);
58 if (page_offset
> num_pages
)
59 return VM_FAULT_SIGBUS
;
62 mutex_lock(&obj
->pages_lock
);
64 get_page(obj
->pages
[page_offset
]);
65 vmf
->page
= obj
->pages
[page_offset
];
68 mutex_unlock(&obj
->pages_lock
);
71 struct address_space
*mapping
;
73 mapping
= file_inode(obj
->gem
.filp
)->i_mapping
;
74 page
= shmem_read_mapping_page(mapping
, page_offset
);
80 switch (PTR_ERR(page
)) {
90 ret
= VM_FAULT_SIGBUS
;
93 WARN_ON(PTR_ERR(page
));
94 ret
= VM_FAULT_SIGBUS
;
102 struct drm_gem_object
*vkms_gem_create(struct drm_device
*dev
,
103 struct drm_file
*file
,
107 struct vkms_gem_object
*obj
;
110 if (!file
|| !dev
|| !handle
)
111 return ERR_PTR(-EINVAL
);
113 obj
= __vkms_gem_create(dev
, size
);
115 return ERR_CAST(obj
);
117 ret
= drm_gem_handle_create(file
, &obj
->gem
, handle
);
118 drm_gem_object_put_unlocked(&obj
->gem
);
120 drm_gem_object_release(&obj
->gem
);
128 int vkms_dumb_create(struct drm_file
*file
, struct drm_device
*dev
,
129 struct drm_mode_create_dumb
*args
)
131 struct drm_gem_object
*gem_obj
;
134 if (!args
|| !dev
|| !file
)
137 pitch
= args
->width
* DIV_ROUND_UP(args
->bpp
, 8);
138 size
= pitch
* args
->height
;
143 gem_obj
= vkms_gem_create(dev
, file
, &args
->handle
, size
);
145 return PTR_ERR(gem_obj
);
147 args
->size
= gem_obj
->size
;
150 DRM_DEBUG_DRIVER("Created object of size %lld\n", size
);
155 int vkms_dumb_map(struct drm_file
*file
, struct drm_device
*dev
,
156 u32 handle
, u64
*offset
)
158 struct drm_gem_object
*obj
;
161 obj
= drm_gem_object_lookup(file
, handle
);
170 ret
= drm_gem_create_mmap_offset(obj
);
174 *offset
= drm_vma_node_offset_addr(&obj
->vma_node
);
176 drm_gem_object_put_unlocked(obj
);