mirror of
https://github.com/torvalds/linux.git
synced 2026-04-21 00:04:01 -04:00
This was done entirely with mindless brute force, using
git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' |
xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/'
to convert the new alloc_obj() users that had a simple GFP_KERNEL
argument to just drop that argument.
Note that due to the extreme simplicity of the scripting, any slightly
more complex cases spread over multiple lines would not be triggered:
they definitely exist, but this covers the vast bulk of the cases, and
the resulting diff is also then easier to check automatically.
For the same reason the 'flex' versions will be done as a separate
conversion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
175 lines
3.6 KiB
C
175 lines
3.6 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2020 Intel Corporation
|
|
*/
|
|
|
|
#include <linux/iosys-map.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/pagemap.h>
|
|
#include <linux/shmem_fs.h>
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include "i915_drv.h"
|
|
#include "gem/i915_gem_object.h"
|
|
#include "gem/i915_gem_lmem.h"
|
|
#include "shmem_utils.h"
|
|
|
|
struct file *shmem_create_from_data(const char *name, void *data, size_t len)
|
|
{
|
|
struct file *file;
|
|
int err;
|
|
|
|
file = shmem_file_setup(name, PAGE_ALIGN(len),
|
|
mk_vma_flags(VMA_NORESERVE_BIT));
|
|
if (IS_ERR(file))
|
|
return file;
|
|
|
|
err = shmem_write(file, 0, data, len);
|
|
if (err) {
|
|
fput(file);
|
|
return ERR_PTR(err);
|
|
}
|
|
|
|
return file;
|
|
}
|
|
|
|
struct file *shmem_create_from_object(struct drm_i915_gem_object *obj)
|
|
{
|
|
enum i915_map_type map_type;
|
|
struct file *file;
|
|
void *ptr;
|
|
|
|
if (i915_gem_object_is_shmem(obj)) {
|
|
file = obj->base.filp;
|
|
get_file(file);
|
|
return file;
|
|
}
|
|
|
|
map_type = i915_gem_object_is_lmem(obj) ? I915_MAP_WC : I915_MAP_WB;
|
|
ptr = i915_gem_object_pin_map_unlocked(obj, map_type);
|
|
if (IS_ERR(ptr))
|
|
return ERR_CAST(ptr);
|
|
|
|
file = shmem_create_from_data("", ptr, obj->base.size);
|
|
i915_gem_object_unpin_map(obj);
|
|
|
|
return file;
|
|
}
|
|
|
|
void *shmem_pin_map(struct file *file)
|
|
{
|
|
struct page **pages;
|
|
size_t n_pages, i;
|
|
void *vaddr;
|
|
|
|
n_pages = file->f_mapping->host->i_size >> PAGE_SHIFT;
|
|
pages = kvmalloc_objs(*pages, n_pages);
|
|
if (!pages)
|
|
return NULL;
|
|
|
|
for (i = 0; i < n_pages; i++) {
|
|
pages[i] = shmem_read_mapping_page_gfp(file->f_mapping, i,
|
|
GFP_KERNEL);
|
|
if (IS_ERR(pages[i]))
|
|
goto err_page;
|
|
}
|
|
|
|
vaddr = vmap(pages, n_pages, VM_MAP_PUT_PAGES, PAGE_KERNEL);
|
|
if (!vaddr)
|
|
goto err_page;
|
|
mapping_set_unevictable(file->f_mapping);
|
|
return vaddr;
|
|
err_page:
|
|
while (i--)
|
|
put_page(pages[i]);
|
|
kvfree(pages);
|
|
return NULL;
|
|
}
|
|
|
|
void shmem_unpin_map(struct file *file, void *ptr)
|
|
{
|
|
mapping_clear_unevictable(file->f_mapping);
|
|
vfree(ptr);
|
|
}
|
|
|
|
static int __shmem_rw(struct file *file, loff_t off,
|
|
void *ptr, size_t len,
|
|
bool write)
|
|
{
|
|
unsigned long pfn;
|
|
|
|
for (pfn = off >> PAGE_SHIFT; len; pfn++) {
|
|
unsigned int this =
|
|
min_t(size_t, PAGE_SIZE - offset_in_page(off), len);
|
|
struct page *page;
|
|
void *vaddr;
|
|
|
|
page = shmem_read_mapping_page_gfp(file->f_mapping, pfn,
|
|
GFP_KERNEL);
|
|
if (IS_ERR(page))
|
|
return PTR_ERR(page);
|
|
|
|
vaddr = kmap_local_page(page);
|
|
if (write) {
|
|
memcpy(vaddr + offset_in_page(off), ptr, this);
|
|
set_page_dirty(page);
|
|
} else {
|
|
memcpy(ptr, vaddr + offset_in_page(off), this);
|
|
}
|
|
mark_page_accessed(page);
|
|
kunmap_local(vaddr);
|
|
put_page(page);
|
|
|
|
len -= this;
|
|
ptr += this;
|
|
off = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int shmem_read_to_iosys_map(struct file *file, loff_t off,
|
|
struct iosys_map *map, size_t map_off, size_t len)
|
|
{
|
|
unsigned long pfn;
|
|
|
|
for (pfn = off >> PAGE_SHIFT; len; pfn++) {
|
|
unsigned int this =
|
|
min_t(size_t, PAGE_SIZE - offset_in_page(off), len);
|
|
struct page *page;
|
|
void *vaddr;
|
|
|
|
page = shmem_read_mapping_page_gfp(file->f_mapping, pfn,
|
|
GFP_KERNEL);
|
|
if (IS_ERR(page))
|
|
return PTR_ERR(page);
|
|
|
|
vaddr = kmap_local_page(page);
|
|
iosys_map_memcpy_to(map, map_off, vaddr + offset_in_page(off),
|
|
this);
|
|
mark_page_accessed(page);
|
|
kunmap_local(vaddr);
|
|
put_page(page);
|
|
|
|
len -= this;
|
|
map_off += this;
|
|
off = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int shmem_read(struct file *file, loff_t off, void *dst, size_t len)
|
|
{
|
|
return __shmem_rw(file, off, dst, len, false);
|
|
}
|
|
|
|
int shmem_write(struct file *file, loff_t off, void *src, size_t len)
|
|
{
|
|
return __shmem_rw(file, off, src, len, true);
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
|
#include "st_shmem_utils.c"
|
|
#endif
|