// SPDX-License-Identifier: MIT
/*
* Copyright © 2021 Intel Corporation
*/
#include <linux/shmem_fs.h>
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_tt.h>
#include <drm/drm_buddy.h>
#include "i915_drv.h"
#include "i915_ttm_buddy_manager.h"
#include "intel_memory_region.h"
#include "intel_region_ttm.h"
#include "gem/i915_gem_mman.h"
#include "gem/i915_gem_object.h"
#include "gem/i915_gem_region.h"
#include "gem/i915_gem_ttm.h"
#include "gem/i915_gem_ttm_move.h"
#include "gem/i915_gem_ttm_pm.h"
#include "gt/intel_gpu_commands.h"
#define I915_TTM_PRIO_PURGE 0
#define I915_TTM_PRIO_NO_PAGES 1
#define I915_TTM_PRIO_HAS_PAGES 2
#define I915_TTM_PRIO_NEEDS_CPU_ACCESS 3
/*
* Size of struct ttm_place vector in on-stack struct ttm_placement allocs
*/
#define I915_TTM_MAX_PLACEMENTS INTEL_REGION_UNKNOWN
/**
* struct i915_ttm_tt - TTM page vector with additional private information
* @ttm: The base TTM page vector.
* @dev: The struct device used for dma mapping and unmapping.
* @cached_rsgt: The cached scatter-gather table.
* @is_shmem: Set if using shmem.
* @filp: The shmem file, if using shmem backend.
*
* Note that DMA may be going on right up to the point where the page-
* vector is unpopulated in delayed destroy. Hence keep the
* scatter-gather table mapped and cached up to that point. This is
* different from the cached gem object io scatter-gather table which
* doesn't have an associated dma mapping.
*/
struct i915_ttm_tt {
struct ttm_tt ttm;
struct device *dev;
struct i915_refct_sgt cached_rsgt;
bool is_shmem;
struct file *filp;
};
static const struct ttm_place sys_placement_flags = {
.fpfn = 0,
.lpfn = 0,
.mem_type = I915_PL_SYSTEM,
.flags = 0,
};
static struct ttm_placement i915_sys_placement = {
.num_placement = 1,
.placement = &sys_placement_flags,
.num_busy_placement = 1,
.busy_placement = &sys_placement_flags,
};
/**
* i915_ttm_sys_placement - Return the struct ttm_placement to be
* used for an object in system memory.
*
* Rather than making the struct extern, use this
* function.
*
* Return: A pointer to a static variable for sys placement.
*/
struct ttm_placement *i915_ttm_sys_placement(void)
{
return &i915_sys_placement;
}
static int i915_ttm_err_to_gem(int err)
{
/* Fastpath */
if (likely(!err))
return 0;
switch (err) {
case -EBUSY:
/*
* TTM likes to convert -EDEADLK to -EBUSY, and wants us to
* restart the operation, since we don't record the contending
* lock. We use -EAGAIN to restart.
*/
return -EAGAIN;
case -ENOSPC:
/*
* Memory type / region is full, and we can't evict.
* Except possibly system, that returns -ENOMEM;
*/
return -ENXIO;
default:
break