linux/drivers/dma-buf/dma-resv.c

// SPDX-License-Identifier: MIT
/*
 * Copyright (C) 2012-2014 Canonical Ltd (Maarten Lankhorst)
 *
 * Based on bo.c which bears the following copyright notice,
 * but is dual licensed:
 *
 * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/
/*
 * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
 */

#include <linux/dma-resv.h>
#include <linux/dma-fence-array.h>
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/sched/mm.h>
#include <linux/mmu_notifier.h>
#include <linux/seq_file.h>

/**
 * DOC: Reservation Object Overview
 *
 * The reservation object provides a mechanism to manage a container of
 * dma_fence object associated with a resource. A reservation object
 * can have any number of fences attaches to it. Each fence carries an usage
 * parameter determining how the operation represented by the fence is using the
 * resource. The RCU mechanism is used to protect read access to fences from
 * locked write-side updates.
 *
 * See struct dma_resv for more details.
 */

DEFINE_WD_CLASS();
EXPORT_SYMBOL();

/* Mask for the lower fence pointer bits */
#define DMA_RESV_LIST_MASK

struct dma_resv_list {};

/* Extract the fence and usage flags from an RCU protected entry in the list. */
static void dma_resv_list_entry(struct dma_resv_list *list, unsigned int index,
				struct dma_resv *resv, struct dma_fence **fence,
				enum dma_resv_usage *usage)
{}

/* Set the fence and usage flags at the specific index in the list. */
static void dma_resv_list_set(struct dma_resv_list *list,
			      unsigned int index,
			      struct dma_fence *fence,
			      enum dma_resv_usage usage)
{}

/*
 * Allocate a new dma_resv_list and make sure to correctly initialize
 * max_fences.
 */
static struct dma_resv_list *dma_resv_list_alloc(unsigned int max_fences)
{}

/* Free a dma_resv_list and make sure to drop all references. */
static void dma_resv_list_free(struct dma_resv_list *list)
{}

/**
 * dma_resv_init - initialize a reservation object
 * @obj: the reservation object
 */
void dma_resv_init(struct dma_resv *obj)
{}
EXPORT_SYMBOL();

/**
 * dma_resv_fini - destroys a reservation object
 * @obj: the reservation object
 */
void dma_resv_fini(struct dma_resv *obj)
{}
EXPORT_SYMBOL();

/* Dereference the fences while ensuring RCU rules */
static inline struct dma_resv_list *dma_resv_fences_list(struct dma_resv *obj)
{}

/**
 * dma_resv_reserve_fences - Reserve space to add fences to a dma_resv object.
 * @obj: reservation object
 * @num_fences: number of fences we want to add
 *
 * Should be called before dma_resv_add_fence().  Must be called with @obj
 * locked through dma_resv_lock().
 *
 * Note that the preallocated slots need to be re-reserved if @obj is unlocked
 * at any time before calling dma_resv_add_fence(). This is validated when
 * CONFIG_DEBUG_MUTEXES is enabled.
 *
 * RETURNS
 * Zero for success, or -errno
 */
int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
{}
EXPORT_SYMBOL();

#ifdef CONFIG_DEBUG_MUTEXES
/**
 * dma_resv_reset_max_fences - reset fences for debugging
 * @obj: the dma_resv object to reset
 *
 * Reset the number of pre-reserved fence slots to test that drivers do
 * correct slot allocation using dma_resv_reserve_fences(). See also
 * &dma_resv_list.max_fences.
 */
void dma_resv_reset_max_fences(struct dma_resv *obj)
{}
EXPORT_SYMBOL();
#endif

/**
 * dma_resv_add_fence - Add a fence to the dma_resv obj
 * @obj: the reservation object
 * @fence: the fence to add
 * @usage: how the fence is used, see enum dma_resv_usage
 *
 * Add a fence to a slot, @obj must be locked with dma_resv_lock(), and
 * dma_resv_reserve_fences() has been called.
 *
 * See also &dma_resv.fence for a discussion of the semantics.
 */
void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
			enum dma_resv_usage usage)
{}
EXPORT_SYMBOL();

/**
 * dma_resv_replace_fences - replace fences in the dma_resv obj
 * @obj: the reservation object
 * @context: the context of the fences to replace
 * @replacement: the new fence to use instead
 * @usage: how the new fence is used, see enum dma_resv_usage
 *
 * Replace fences with a specified context with a new fence. Only valid if the
 * operation represented by the original fence has no longer access to the
 * resources represented by the dma_resv object when the new fence completes.
 *
 * And example for using this is replacing a preemption fence with a page table
 * update fence which makes the resource inaccessible.
 */
void dma_resv_replace_fences(struct dma_resv *obj, uint64_t context,
			     struct dma_fence *replacement,
			     enum dma_resv_usage usage)
{}
EXPORT_SYMBOL();

/* Restart the unlocked iteration by initializing the cursor object. */
static void dma_resv_iter_restart_unlocked(struct dma_resv_iter *cursor)
{}

/* Walk to the next not signaled fence and grab a reference to it */
static void dma_resv_iter_walk_unlocked(struct dma_resv_iter *cursor)
{}

/**
 * dma_resv_iter_first_unlocked - first fence in an unlocked dma_resv obj.
 * @cursor: the cursor with the current position
 *
 * Subsequent fences are iterated with dma_resv_iter_next_unlocked().
 *
 * Beware that the iterator can be restarted.  Code which accumulates statistics
 * or similar needs to check for this with dma_resv_iter_is_restarted(). For
 * this reason prefer the locked dma_resv_iter_first() whenever possible.
 *
 * Returns the first fence from an unlocked dma_resv obj.
 */
struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor)
{}
EXPORT_SYMBOL();

/**
 * dma_resv_iter_next_unlocked - next fence in an unlocked dma_resv obj.
 * @cursor: the cursor with the current position
 *
 * Beware that the iterator can be restarted.  Code which accumulates statistics
 * or similar needs to check for this with dma_resv_iter_is_restarted(). For
 * this reason prefer the locked dma_resv_iter_next() whenever possible.
 *
 * Returns the next fence from an unlocked dma_resv obj.
 */
struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
{}
EXPORT_SYMBOL();

/**
 * dma_resv_iter_first - first fence from a locked dma_resv object
 * @cursor: cursor to record the current position
 *
 * Subsequent fences are iterated with dma_resv_iter_next_unlocked().
 *
 * Return the first fence in the dma_resv object while holding the
 * &dma_resv.lock.
 */
struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_iter_next - next fence from a locked dma_resv object
 * @cursor: cursor to record the current position
 *
 * Return the next fences from the dma_resv object while holding the
 * &dma_resv.lock.
 */
struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_copy_fences - Copy all fences from src to dst.
 * @dst: the destination reservation object
 * @src: the source reservation object
 *
 * Copy all fences from src to dst. dst-lock must be held.
 */
int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
{}
EXPORT_SYMBOL();

/**
 * dma_resv_get_fences - Get an object's fences
 * fences without update side lock held
 * @obj: the reservation object
 * @usage: controls which fences to include, see enum dma_resv_usage.
 * @num_fences: the number of fences returned
 * @fences: the array of fence ptrs returned (array is krealloc'd to the
 * required size, and must be freed by caller)
 *
 * Retrieve all fences from the reservation object.
 * Returns either zero or -ENOMEM.
 */
int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
			unsigned int *num_fences, struct dma_fence ***fences)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_get_singleton - Get a single fence for all the fences
 * @obj: the reservation object
 * @usage: controls which fences to include, see enum dma_resv_usage.
 * @fence: the resulting fence
 *
 * Get a single fence representing all the fences inside the resv object.
 * Returns either 0 for success or -ENOMEM.
 *
 * Warning: This can't be used like this when adding the fence back to the resv
 * object since that can lead to stack corruption when finalizing the
 * dma_fence_array.
 *
 * Returns 0 on success and negative error values on failure.
 */
int dma_resv_get_singleton(struct dma_resv *obj, enum dma_resv_usage usage,
			   struct dma_fence **fence)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_wait_timeout - Wait on reservation's objects fences
 * @obj: the reservation object
 * @usage: controls which fences to include, see enum dma_resv_usage.
 * @intr: if true, do interruptible wait
 * @timeout: timeout value in jiffies or zero to return immediately
 *
 * Callers are not required to hold specific locks, but maybe hold
 * dma_resv_lock() already
 * RETURNS
 * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
 * greater than zero on success.
 */
long dma_resv_wait_timeout(struct dma_resv *obj, enum dma_resv_usage usage,
			   bool intr, unsigned long timeout)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_set_deadline - Set a deadline on reservation's objects fences
 * @obj: the reservation object
 * @usage: controls which fences to include, see enum dma_resv_usage.
 * @deadline: the requested deadline (MONOTONIC)
 *
 * May be called without holding the dma_resv lock.  Sets @deadline on
 * all fences filtered by @usage.
 */
void dma_resv_set_deadline(struct dma_resv *obj, enum dma_resv_usage usage,
			   ktime_t deadline)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_test_signaled - Test if a reservation object's fences have been
 * signaled.
 * @obj: the reservation object
 * @usage: controls which fences to include, see enum dma_resv_usage.
 *
 * Callers are not required to hold specific locks, but maybe hold
 * dma_resv_lock() already.
 *
 * RETURNS
 *
 * True if all fences signaled, else false.
 */
bool dma_resv_test_signaled(struct dma_resv *obj, enum dma_resv_usage usage)
{}
EXPORT_SYMBOL_GPL();

/**
 * dma_resv_describe - Dump description of the resv object into seq_file
 * @obj: the reservation object
 * @seq: the seq_file to dump the description into
 *
 * Dump a textual description of the fences inside an dma_resv object into the
 * seq_file.
 */
void dma_resv_describe(struct dma_resv *obj, struct seq_file *seq)
{}
EXPORT_SYMBOL_GPL();

#if IS_ENABLED(CONFIG_LOCKDEP)
static int __init dma_resv_lockdep(void)
{}
subsys_initcall(dma_resv_lockdep);
#endif