Files
linux-nvgpu/drivers/gpu/nvgpu/include/nvgpu/channel.h
atanand eae4593343 gpu: nvgpu: add ioctl to configure implicit ERRBAR
Add ioctl support to configure implicit ERRBAR by setting/unsetting
NV_PGRAPH_PRI_GPCS_TPCS_SM_SCH_MACRO_SCHED register.

Add gpu characteritics flag: NVGPU_SCHED_EXIT_WAIT_FOR_ERRBAR_SUPPORTED
to allow userspace driver to determine if implicit ERRBAR ioctl is
supported.

Bug: 200782861

Change-Id: I530a4cf73bc5c844e8d73094d3e23949568fe335
Signed-off-by: atanand <atanand@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2718672
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Sagar Kamble <skamble@nvidia.com>
Reviewed-by: Vaibhav Kachore <vkachore@nvidia.com>
GVS: Gerrit_Virtual_Submit
2022-08-05 23:10:18 -07:00

1222 lines
37 KiB
C

/*
* Copyright (c) 2018-2022, NVIDIA CORPORATION. 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#ifndef NVGPU_CHANNEL_H
#define NVGPU_CHANNEL_H
#include <nvgpu/list.h>
#include <nvgpu/lock.h>
#include <nvgpu/timers.h>
#include <nvgpu/cond.h>
#include <nvgpu/atomic.h>
#include <nvgpu/nvgpu_mem.h>
#include <nvgpu/allocator.h>
#include <nvgpu/debug.h>
/**
* @file
*
* Channel interface.
*/
struct gk20a;
struct dbg_session_gk20a;
struct nvgpu_fence_type;
struct nvgpu_swprofiler;
struct nvgpu_channel_sync;
struct nvgpu_gpfifo_userdata;
struct nvgpu_gr_subctx;
struct nvgpu_gr_ctx;
struct nvgpu_debug_context;
struct priv_cmd_queue;
struct priv_cmd_entry;
struct nvgpu_channel_wdt;
struct nvgpu_user_fence;
struct nvgpu_runlist;
/**
* S/W defined invalid channel identifier.
*/
#define NVGPU_INVALID_CHANNEL_ID (~U32(0U))
/**
* Enable VPR support.
*/
#define NVGPU_SETUP_BIND_FLAGS_SUPPORT_VPR BIT32(0)
/**
* Channel must have deterministic (and low) submit latency.
* This flag is only valid for kernel mode submit.
*/
#define NVGPU_SETUP_BIND_FLAGS_SUPPORT_DETERMINISTIC BIT32(1)
/**
* Enable replayable faults.
*/
#define NVGPU_SETUP_BIND_FLAGS_REPLAYABLE_FAULTS_ENABLE BIT32(2)
/**
* Enable usermode submit (mutually exclusive with kernel_mode submit).
*/
#define NVGPU_SETUP_BIND_FLAGS_USERMODE_SUPPORT BIT32(3)
/**
* Insert a wait on previous job's completion fence, before gpfifo entries.
* See also #nvgpu_fence.
*/
#define NVGPU_SUBMIT_FLAGS_FENCE_WAIT BIT32(0)
/**
* Insert a job completion fence update after gpfifo entries, and return the
* new fence for others to wait on.
*/
#define NVGPU_SUBMIT_FLAGS_FENCE_GET BIT32(1)
/**
* Use HW GPFIFO entry format.
*/
#define NVGPU_SUBMIT_FLAGS_HW_FORMAT BIT32(2)
/**
* Interpret fence as a sync fence fd instead of raw syncpoint fence.
*/
#define NVGPU_SUBMIT_FLAGS_SYNC_FENCE BIT32(3)
/**
* Suppress WFI before fence trigger.
*/
#define NVGPU_SUBMIT_FLAGS_SUPPRESS_WFI BIT32(4)
/**
* Skip buffer refcounting during submit.
*/
#define NVGPU_SUBMIT_FLAGS_SKIP_BUFFER_REFCOUNTING BIT32(5)
/**
* The binary format of 'struct nvgpu_channel_fence' introduced here
* should match that of 'struct nvgpu_fence' defined in uapi header, since
* this struct is intended to be a mirror copy of the uapi struct. This is
* not a hard requirement though because of nvgpu_get_fence_args conversion
* function.
*
* See also #nvgpu_fence.
*/
struct nvgpu_channel_fence {
/** Syncpoint Id */
u32 id;
/** Syncpoint value to wait on, or for others to wait */
u32 value;
};
/**
* The binary format of 'struct nvgpu_gpfifo_entry' introduced here
* should match that of 'struct nvgpu_gpfifo' defined in uapi header, since
* this struct is intended to be a mirror copy of the uapi struct. This is
* a rigid requirement because there's no conversion function and there are
* memcpy's present between the user gpfifo (of type nvgpu_gpfifo) and the
* kern gpfifo (of type nvgpu_gpfifo_entry).
*
* See also #nvgpu_gpfifo.
*/
struct nvgpu_gpfifo_entry {
/** First word of gpfifo entry. */
u32 entry0;
/** Second word of gpfifo entry. */
u32 entry1;
};
struct gpfifo_desc {
/** Memory area containing gpfifo entries. */
struct nvgpu_mem mem;
/** Number of entries in gpfifo. */
u32 entry_num;
/** Index to last gpfifo entry read by H/W. */
u32 get;
/** Index to next gpfifo entry to write to. */
u32 put;
#ifdef CONFIG_NVGPU_DGPU
/**
* If gpfifo lives in vidmem or is forced to go via PRAMIN, first copy
* from userspace to pipe and then from pipe to gpu buffer.
*/
void *pipe;
#endif
};
#define NVGPU_CHANNEL_STATUS_STRING_LENGTH 120U
/**
* Structure abstracting H/W state for channel.
* Used when unbinding a channel from TSG.
* See #nvgpu_tsg_unbind_channel_hw_state_check.
*/
struct nvgpu_channel_hw_state {
/** Channel scheduling is enabled. */
bool enabled;
/** Channel is next to run when TSG is scheduled. */
bool next;
/** Channel context's was preempted and needs to be reloaded. */
bool ctx_reload;
/** Channel has work to do in its GPFIFO. */
bool busy;
/** Channel is pending on a semaphore/syncpoint acquire. */
bool pending_acquire;
/** Channel has encountered an engine page fault. */
bool eng_faulted;
/** Human-readable status string. */
char status_string[NVGPU_CHANNEL_STATUS_STRING_LENGTH];
};
/**
* Structure used to take a snapshot of channel status, in order
* to dump it. See #nvgpu_channel_debug_dump_all.
*/
struct nvgpu_channel_dump_info {
/** Channel Identifier. */
u32 chid;
/** TSG Identifier. */
u32 tsgid;
/** Pid of the process that created this channel. */
int pid;
/** Number of references to this channel. */
int refs;
/** Channel uses deterministic submit (kernel submit only). */
bool deterministic;
/** Channel H/W state */
struct nvgpu_channel_hw_state hw_state;
/** Snapshot of channel instance fields. */
struct {
u64 pb_top_level_get;
u64 pb_put;
u64 pb_get;
u64 pb_fetch;
u32 pb_header;
u32 pb_count;
u64 sem_addr;
u64 sem_payload;
u32 sem_execute;
u32 syncpointa;
u32 syncpointb;
u32 semaphorea;
u32 semaphoreb;
u32 semaphorec;
u32 semaphored;
} inst;
/** Semaphore status. */
struct {
u32 value;
u32 next;
u64 addr;
} sema;
char nvs_domain_name[32];
};
/**
* The binary format of 'struct nvgpu_setup_bind_args' introduced here
* should match that of 'struct nvgpu_channel_setup_bind_args' defined in
* uapi header, since this struct is intended to be a mirror copy of the
* uapi struct. This is not a hard requirement though because of
* #nvgpu_get_setup_bind_args conversion function.
*
* See also #nvgpu_channel_setup_bind_args.
*/
struct nvgpu_setup_bind_args {
u32 num_gpfifo_entries;
u32 num_inflight_jobs;
u32 userd_dmabuf_fd;
u64 userd_dmabuf_offset;
u32 gpfifo_dmabuf_fd;
u64 gpfifo_dmabuf_offset;
u32 work_submit_token;
u32 flags;
};
/**
* The binary format of 'struct notification' introduced here
* should match that of 'struct nvgpu_notification' defined in uapi header,
* since this struct is intended to be a mirror copy of the uapi struct.
* This is hard requirement, because there is no conversion function.
*
* See also #nvgpu_notification.
*/
struct notification {
struct {
u32 nanoseconds[2];
} timestamp;
u32 info32;
u16 info16;
u16 status;
};
struct nvgpu_channel_joblist {
struct {
unsigned int length;
unsigned int put;
unsigned int get;
struct nvgpu_channel_job *jobs;
struct nvgpu_mutex read_lock;
} pre_alloc;
};
/**
* Track refcount actions, saving their stack traces. This number specifies how
* many most recent actions are stored in a buffer. Set to 0 to disable. 128
* should be enough to track moderately hard problems from the start.
*/
#define GK20A_CHANNEL_REFCOUNT_TRACKING 0
#if GK20A_CHANNEL_REFCOUNT_TRACKING
/**
* Stack depth for the saved actions.
*/
#define GK20A_CHANNEL_REFCOUNT_TRACKING_STACKLEN 8
/**
* Because the puts and gets are not linked together explicitly (although they
* should always come in pairs), it's not possible to tell which ref holder to
* delete from the list when doing a put. So, just store some number of most
* recent gets and puts in a ring buffer, to obtain a history.
*
* These are zeroed when a channel is closed, so a new one starts fresh.
*/
enum nvgpu_channel_ref_action_type {
channel_gk20a_ref_action_get,
channel_gk20a_ref_action_put
};
#include <linux/stacktrace.h>
struct nvgpu_channel_ref_action {
enum nvgpu_channel_ref_action_type type;
s64 timestamp_ms;
/*
* Many of these traces will be similar. Simpler to just capture
* duplicates than to have a separate database for the entries.
*/
struct stack_trace trace;
unsigned long trace_entries[GK20A_CHANNEL_REFCOUNT_TRACKING_STACKLEN];
};
#endif
struct nvgpu_channel_user_syncpt;
/** Channel context */
struct nvgpu_channel {
/** Pointer to GPU context. Set only when channel is active. */
struct gk20a *g;
/** Channel's entry in list of free channels. */
struct nvgpu_list_node free_chs;
/** Spinlock to acquire a reference on the channel. */
struct nvgpu_spinlock ref_obtain_lock;
/** Number of references to this channel. */
nvgpu_atomic_t ref_count;
/** Wait queue to wait on reference decrement. */
struct nvgpu_cond ref_count_dec_wq;
#if GK20A_CHANNEL_REFCOUNT_TRACKING
/**
* Ring buffer for most recent refcount gets and puts. Protected by
* #ref_actions_lock when getting or putting refs (i.e., adding
* entries), and when reading entries.
*/
struct nvgpu_channel_ref_action ref_actions[
GK20A_CHANNEL_REFCOUNT_TRACKING];
size_t ref_actions_put; /* index of next write */
struct nvgpu_spinlock ref_actions_lock;
#endif
/**
* Channel instance has been bound to hardware (i.e. instance block
* has been set up, and bound in CCSR).
*/
nvgpu_atomic_t bound;
/** Channel Identifier. */
u32 chid;
/** TSG Identifier. */
u32 tsgid;
/**
* Thread identifier of the thread that created the channel.
* The naming is as per Linux kernel semantic, where each thread actually
* gets a distinct pid.
*/
pid_t pid;
/**
* Process identifier of the thread that created the channel.
* The naming of this variable is as per Linux kernel semantic,
* where each thread in a process share the same Thread Group Id.
* Confusingly, at userspace level, this is what is seen as the "pid".
*/
pid_t tgid;
/** Lock to serialize ioctls for this channel. */
struct nvgpu_mutex ioctl_lock;
/** Channel's entry in TSG's channel list. */
struct nvgpu_list_node ch_entry;
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
struct nvgpu_channel_joblist joblist;
struct gpfifo_desc gpfifo;
struct priv_cmd_queue *priv_cmd_q;
struct nvgpu_channel_sync *sync;
/* for job cleanup handling in the background worker */
struct nvgpu_list_node worker_item;
#endif /* CONFIG_NVGPU_KERNEL_MODE_SUBMIT */
/* kernel watchdog to kill stuck jobs */
struct nvgpu_channel_wdt *wdt;
bool wdt_debug_dump;
/** Fence allocator in case of deterministic submit. */
struct nvgpu_allocator fence_allocator;
/** Channel's virtual memory. */
struct vm_gk20a *vm;
/** USERD memory for usermode submit. */
struct nvgpu_mem usermode_userd;
/** GPFIFO memory for usermode submit. */
struct nvgpu_mem usermode_gpfifo;
/** Channel instance block memory. */
struct nvgpu_mem inst_block;
/**
* USERD address that will be programmed in H/W.
* It depends on whether usermode submit is enabled or not.
*/
u64 userd_iova;
/**
* If kernel mode submit is enabled, userd_mem points to
* one userd slab, and userd_offset indicates the offset in bytes
* from the start of this slab.
* If user mode submit is enabled, userd_mem points to usermode_userd,
* and userd_offset is 0.
*/
struct nvgpu_mem *userd_mem;
/** Offset from the start of userd_mem (in bytes). */
u32 userd_offset;
/** Notifier wait queue (see #NVGPU_WAIT_TYPE_NOTIFIER). */
struct nvgpu_cond notifier_wq;
/** Semaphore wait queue (see #NVPGU_WAIT_TYPE_SEMAPHORE). */
struct nvgpu_cond semaphore_wq;
#if defined(CONFIG_NVGPU_CYCLESTATS)
struct {
void *cyclestate_buffer;
u32 cyclestate_buffer_size;
struct nvgpu_mutex cyclestate_buffer_mutex;
} cyclestate;
struct nvgpu_mutex cs_client_mutex;
struct gk20a_cs_snapshot_client *cs_client;
#endif
#ifdef CONFIG_NVGPU_DEBUGGER
/** Channel's debugger session lock. */
struct nvgpu_mutex dbg_s_lock;
/** Channel entry in debugger session's list. */
struct nvgpu_list_node dbg_s_list;
#endif
/** Syncpoint lock to allocate fences. */
struct nvgpu_mutex sync_lock;
#ifdef CONFIG_TEGRA_GK20A_NVHOST
/** Syncpoint for usermode submit case. */
struct nvgpu_channel_user_syncpt *user_sync;
#endif
#ifdef CONFIG_NVGPU_GR_VIRTUALIZATION
/** Channel handle for vgpu case. */
u64 virt_ctx;
#endif
/** Channel's graphics subcontext. */
struct nvgpu_gr_subctx *subctx;
/** Lock to access unserviceable state. */
struct nvgpu_spinlock unserviceable_lock;
/**
* An uncorrectable error has occurred on the channel.
* It is not possible to take more references on this channel,
* and only available option for userspace is to close the
* channel fd.
*/
bool unserviceable;
/** Any operating system specific data. */
void *os_priv;
/** We support only one object per channel */
u32 obj_class;
/**
* Accumulated context switch timeouts in ms.
* On context switch timeout interrupt, if
* #ctxsw_timeout_max_ms is > 0, we check if there was any
* progress with pending work in gpfifo. If not, timeouts
* are accumulated in #ctxsw_timeout_accumulated_ms.
*/
u32 ctxsw_timeout_accumulated_ms;
/**
* GP_GET value read at last context switch timeout. It is
* compared with current H/W value for GP_GET to determine
* if H/W made any progress processing the gpfifo.
*/
u32 ctxsw_timeout_gpfifo_get;
/**
* Maximum accumulated context switch timeout in ms.
* Above this limit, the channel is considered to have
* timed out. If recovery is enabled, engine is reset.
*/
u32 ctxsw_timeout_max_ms;
/**
* Indicates if detailed information shoud be dumped in case of
* ctxsw timeout.
*/
bool ctxsw_timeout_debug_dump;
/** Subcontext Id (aka. veid). */
u32 subctx_id;
/**
* Selects which PBDMA should run this channel if more than
* one PBDMA is supported by the runlist.
*/
u32 runqueue_sel;
/** Runlist the channel will run on. */
struct nvgpu_runlist *runlist;
/**
* Recovery path can be entered twice for the same error in
* case of mmu_nack. This flag indicates if we already recovered
* for the same context.
*/
bool mmu_nack_handled;
/**
* Indicates if we can take more references on a given channel.
* Typically it is not possible to take more references on a
* free or unserviceable channel.
*/
bool referenceable;
/** True if VPR support was requested during setup bind */
bool vpr;
#ifdef CONFIG_NVGPU_DETERMINISTIC_CHANNELS
/**
* Channel shall exhibit deterministic behavior in the submit path.
* Submit latency shall be consistent (and low). Submits that may cause
* nondeterministic behaviour are not allowed and may fail (for example,
* sync fds or mapped buffer refcounting are not deterministic).
*/
bool deterministic;
/** Deterministic, but explicitly idle and submits disallowed. */
bool deterministic_railgate_allowed;
#endif
/** Channel uses Color Decompression Engine. */
bool cde;
/**
* If enabled, USERD and GPFIFO buffers are handled in userspace.
* Userspace writes a submit token to the doorbell register in the
* usermode region to notify the GPU of new work on this channel.
* Usermode and kernelmode submit modes are mutually exclusive.
* On usermode submit channels, the caller must keep track of GPFIFO
* usage. The recommended way for the current hardware (Maxwell..Turing)
* is to use semaphore releases to track the pushbuffer progress.
*/
bool usermode_submit_enabled;
/**
* Channel is hooked to OS fence framework.
*/
bool has_os_fence_framework_support;
/**
* Privileged channel will be able to execute privileged operations via
* Host methods on its pushbuffer.
*/
bool is_privileged_channel;
#ifdef CONFIG_NVGPU_DEBUGGER
/**
* MMU Debugger Mode is enabled for this channel if refcnt > 0
*/
u32 mmu_debug_mode_refcnt;
/**
* ERRBAR is enabled for this channel if refcnt > 0
*/
nvgpu_atomic_t sched_exit_wait_for_errbar_refcnt;
#endif
};
#ifdef CONFIG_NVGPU_KERNEL_MODE_SUBMIT
int nvgpu_channel_worker_init(struct gk20a *g);
void nvgpu_channel_worker_deinit(struct gk20a *g);
void nvgpu_channel_update(struct nvgpu_channel *c);
u32 nvgpu_channel_update_gpfifo_get_and_get_free_count(
struct nvgpu_channel *ch);
u32 nvgpu_channel_get_gpfifo_free_count(struct nvgpu_channel *ch);
int nvgpu_channel_add_job(struct nvgpu_channel *c,
struct nvgpu_channel_job *job,
bool skip_buffer_refcounting);
void nvgpu_channel_clean_up_jobs(struct nvgpu_channel *c);
void nvgpu_channel_clean_up_deterministic_job(struct nvgpu_channel *c);
int nvgpu_submit_channel_gpfifo_user(struct nvgpu_channel *c,
struct nvgpu_gpfifo_userdata userdata,
u32 num_entries,
u32 flags,
struct nvgpu_channel_fence *fence,
struct nvgpu_user_fence *fence_out,
struct nvgpu_swprofiler *profiler);
int nvgpu_submit_channel_gpfifo_kernel(struct nvgpu_channel *c,
struct nvgpu_gpfifo_entry *gpfifo,
u32 num_entries,
u32 flags,
struct nvgpu_channel_fence *fence,
struct nvgpu_fence_type **fence_out);
#ifdef CONFIG_TEGRA_GK20A_NVHOST
int nvgpu_channel_set_syncpt(struct nvgpu_channel *ch);
#endif
bool nvgpu_channel_update_and_check_ctxsw_timeout(struct nvgpu_channel *ch,
u32 timeout_delta_ms, bool *progress);
static inline bool nvgpu_channel_is_deterministic(struct nvgpu_channel *c)
{
#ifdef CONFIG_NVGPU_DETERMINISTIC_CHANNELS
return c->deterministic;
#else
(void)c;
return false;
#endif
}
#endif /* CONFIG_NVGPU_KERNEL_MODE_SUBMIT */
/**
* @brief Get channel pointer from its node in free channels list.
*
* @param node [in] Pointer to node entry in the list of free channels.
* Cannot be NULL, and must be valid.
*
* @return Channel pointer.
*/
static inline struct nvgpu_channel *
nvgpu_channel_from_free_chs(struct nvgpu_list_node *node)
{
return (struct nvgpu_channel *)
((uintptr_t)node - offsetof(struct nvgpu_channel, free_chs));
};
/**
* @brief Get channel pointer from its node in TSG's channel list.
*
* @param node [in] Pointer to node entry in TSG's channel list.
* Cannot be NULL, and must be valid.
*
* Computes channel pointer from #node pointer.
*
* @return Channel pointer.
*/
static inline struct nvgpu_channel *
nvgpu_channel_from_ch_entry(struct nvgpu_list_node *node)
{
return (struct nvgpu_channel *)
((uintptr_t)node - offsetof(struct nvgpu_channel, ch_entry));
};
/**
* @brief Check if channel is bound to an address space.
*
* @param ch [in] Channel pointer.
*
* @return True if channel is bound to an address space, false otherwise.
*/
static inline bool nvgpu_channel_as_bound(struct nvgpu_channel *ch)
{
return (ch->vm != NULL);
}
/**
* @brief Commit channel's address space.
*
* @param c [in]Channel pointer.
*
* Once a channel is bound to an address space, this function applies
* related settings to channel instance block (e.g. PDB and page size).
*/
void nvgpu_channel_commit_va(struct nvgpu_channel *c);
/**
* @brief Initializes channel context.
*
* @param g [in] Pointer to GPU driver struct.
* @param chid [in] Channel H/W Identifier.
*
* Initializes channel context to default values.
* This includes mutexes and list nodes initialization.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -ENOMEM in case there is not enough memory to allocate channels.
* @retval -EINVAL for invalid condition variable value.
* @retval -EBUSY in case reference condition variable pointer isn't NULL.
* @retval -EFAULT in case any faults occurred while accessing condition
* variable or attribute.
*/
int nvgpu_channel_init_support(struct gk20a *g, u32 chid);
/**
* @brief Initializes channel unit.
*
* @param g [in] Pointer to GPU driver struct.
*
* Gets number of channels from hardware.
* Allocates and initializes channel contexts.
* Initializes mutexes and list of free channels.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -ENOMEM in case there is not enough memory to allocate channels.
* @retval -EINVAL for invalid condition variable value.
* @retval -EBUSY in case reference condition variable pointer isn't NULL.
* @retval -EFAULT in case any faults occurred while accessing condition
* variable or attribute.
*/
int nvgpu_channel_setup_sw(struct gk20a *g);
/**
* @brief De-initializes channel unit.
*
* @param g [in] Pointer to GPU driver struct.
*
* Forcibly closes all opened channels.
* Frees all channel contexts.
* De-initalizes mutexes.
*/
void nvgpu_channel_cleanup_sw(struct gk20a *g);
/**
* @brief Emergency quiescing of channels
*
* @param g [in] Pointer to GPU driver struct.
*
* Driver has encountered uncorrectable error, and is entering
* SW Quiesce state. For each channel:
* - set error notifier
* - mark channel as unserviceable
* - signal on wait queues (notify_wq and semaphore_wq)
*/
void nvgpu_channel_sw_quiesce(struct gk20a *g);
/**
* @brief Close channel
*
* @param ch [in] Channel pointer.
*
* Unbinds channel from TSG, waits until there is no more refs to the channel,
* then frees channel resources.
*
* In case the TSG contains deterministic or usermode submit channels,
* userspace must make sure that the whole TSG is idle, before closing the
* channel. This can be performed by submitting a kickoff containing WFI
* method and waiting for its completion.
*
* @note must be inside gk20a_busy()..gk20a_idle()
*/
void nvgpu_channel_close(struct nvgpu_channel *ch);
/**
* @brief Forcibly close a channel
*
* @param ch [in] Channel pointer.
*
* Forcibly close a channel. It is meant for terminating channels
* when we know the driver is otherwise dying. Ref counts and the like
* are ignored by this version of the cleanup.
*
* @note must be inside gk20a_busy()..gk20a_idle()
*/
void nvgpu_channel_kill(struct nvgpu_channel *ch);
/**
* @brief Mark unrecoverable error for channel
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
*
* An unrecoverable error occurred for the channel. Mark the channel
* as unserviceable, and unblock pending waits on this channel (semaphore
* and error notifier wait queues).
*
* @return True if channel state should be dumped for debug.
*/
bool nvgpu_channel_mark_error(struct gk20a *g, struct nvgpu_channel *ch);
/**
* @brief Abort channel's TSG
*
* @param ch [in] Channel pointer.
* @param preempt [in] True if TSG should be pre-empted
*
* Disables and optionally preempts the channel's TSG.
* Afterwards, all channels in the TSG are marked as unserviceable.
*
* @note: If channel is not bound to a TSG, the call is ignored.
*/
void nvgpu_channel_abort(struct nvgpu_channel *ch, bool channel_preempt);
void nvgpu_channel_abort_clean_up(struct nvgpu_channel *ch);
/**
* @brief Wake up all threads waiting on semaphore wait
*
* @param g [in] Pointer to GPU driver struct.
* @param post_events [in] When true, notify all threads waiting
* on TSG events.
*
* Goes through all channels, and wakes up semaphore wait queue.
* If #post_events is true, it also wakes up TSG event wait queue.
*/
void nvgpu_channel_semaphore_wakeup(struct gk20a *g, bool post_events);
/**
* @brief Enable all channels in channel's TSG
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
*
* Enables all channels that are in the same TSG as #ch.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -EINVAL if channel is not bound to TSG.
*/
int nvgpu_channel_enable_tsg(struct gk20a *g, struct nvgpu_channel *ch);
/**
* @brief Disables all channels in channel's TSG
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
*
* Disables all channels that are in the same TSG as #ch.
* A disable channel is never scheduled to run, even if it is
* next in the runlist.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -EINVAL if channel is not bound to TSG.
*/
int nvgpu_channel_disable_tsg(struct gk20a *g, struct nvgpu_channel *ch);
/**
* @brief Suspend all serviceable channels
*
* @param g [in] Pointer to GPU driver struct.
*
* This function is typically called when preparing power off.
* It disables and preempts all active TSGs, then unbinds all channels contexts
* from hardware (CCSR). Pending channel notifications are cancelled.
* Channels marked as unserviceable are ignored.
*
* @return 0 in case of success, < 0 in case of failure.
*/
int nvgpu_channel_suspend_all_serviceable_ch(struct gk20a *g);
/**
* @brief Resume all serviceable channels
*
* @param g [in] Pointer to GPU driver struct.
*
* Bind all serviceable channels contexts back to hardware.
*
* @return 0 in case of success, < 0 in case of failure.
*/
int nvgpu_channel_resume_all_serviceable_ch(struct gk20a *g);
#ifdef CONFIG_NVGPU_DETERMINISTIC_CHANNELS
/**
* @brief Stop deterministic channel activity for do_idle().
*
* @param g [in] Pointer to GPU driver struct.
*
* Stop deterministic channel activity for do_idle() when power needs to go off
* momentarily but deterministic channels keep power refs for potentially a
* long time.
* Grabs exclusive access to block new deterministic submits, then walks through
* deterministic channels to drop power refs.
*
* @note Must be paired with #nvgpu_channel_deterministic_unidle().
*/
void nvgpu_channel_deterministic_idle(struct gk20a *g);
/**
* @brief Allow deterministic channel activity again for do_unidle().
*
* @param g [in] Pointer to GPU driver struct.
*
* Releases exclusive access to allow again new deterministic submits, then
* walks through deterministic channels to take back power refs.
*
* @note Must be paired with #nvgpu_channel_deterministic_idle().
*/
void nvgpu_channel_deterministic_unidle(struct gk20a *g);
#endif
/**
* @brief Get a reference to the channel.
*
* @param ch [in] Channel pointer.
* @param caller [in] Caller function name (for reference tracking).
*
* Always when a nvgpu_channel pointer is seen and about to be used, a
* reference must be held to it - either by you or the caller, which should be
* documented well or otherwise clearly seen. This usually boils down to the
* file from ioctls directly, or an explicit get in exception handlers when the
* channel is found by a chid.
* @note should always be paired with #nvgpu_channel_put.
*
* @return ch if reference to channel was obtained, NULL otherwise.
* @retval NULL if the channel is dead or being freed elsewhere and you must
* not touch it.
*/
struct nvgpu_channel *nvgpu_channel_get__func(
struct nvgpu_channel *ch, const char *caller);
#define nvgpu_channel_get(ch) nvgpu_channel_get__func(ch, __func__)
/**
* @brief Drop a reference to the channel.
*
* @param ch [in] Channel pointer.
* @param caller [in] Caller function name (for reference tracking).
*
* Drop reference to a channel, when nvgpu_channel pointer is not used anymore.
*/
void nvgpu_channel_put__func(struct nvgpu_channel *ch, const char *caller);
#define nvgpu_channel_put(ch) nvgpu_channel_put__func(ch, __func__)
/**
* @brief Get a reference to the channel by id.
*
* @param g [in] Pointer to GPU driver struct.
* @param chid [in] Channel Identifier.
* @param caller [in] Caller function name (for reference tracking).
*
* Same as #nvgpu_channel_get, except that the channel is first retrieved
* by chid.
*
* @return ch if reference to channel was obtained, NULL otherwise.
* @retval NULL if #chid is invalid, or if the channel is dead or being freed
* elsewhere and should not be used.
*/
struct nvgpu_channel *nvgpu_channel_from_id__func(
struct gk20a *g, u32 chid, const char *caller);
#define nvgpu_channel_from_id(g, chid) \
nvgpu_channel_from_id__func(g, chid, __func__)
/**
* @brief Open and initialize a new channel.
*
* @param g [in] Pointer to GPU driver struct.
* @param runlist_id [in] Runlist Identifer.
* -1 is synonym for #NVGPU_ENGINE_GR.
* @param is_privileged [in] Privileged channel will be able to execute
* privileged operations via Host methods on its
* pushbuffer.
* @param pid [in] pid of current thread (for tracking).
* @param tid [in] tid of current thread (for tracking).
*
* Allocates channel from the free list.
* Allocates channel instance block.
* Set default values for the channel.
*
* @note This function only takes care or the basic channel context
* initialization. Channel still needs an address space, as well as
* a gpfifo and userd to submit some work. It will also need to be
* bound to a TSG, since standalone channels are not supported.
*
* @return channel pointer if channel could be opened, NULL otherwise.
* @retval NULL if there is not enough resources to allocate and
* initialize the channel.
*/
struct nvgpu_channel *nvgpu_channel_open_new(struct gk20a *g,
u32 runlist_id,
bool is_privileged_channel,
pid_t pid, pid_t tid);
/**
* @brief Setup and bind the channel
*
* @param ch [in] Channel pointer.
* @param args [in] Setup bind arguments.
*
* Configures gpfifo and userd for the channel.
* Configures channel instance block and commits it to H/W.
* Adds channel to the runlist.
*
* If #NVGPU_CHANNEL_SETUP_BIND_FLAGS_USERMODE_SUPPORT is specified in
* arguments flags, this function will set up userspace-managed userd and
* gpfifo for the channel, using buffers (dmabuf fd and offsets)
* provided in args. A submit token is passed back to be written in the
* doorbell register in the usermode region to notify the GPU for new
* work on this channel.
*
* @note An address space needs to have been bound to the channel before
* calling this function.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -EINVAL if channel is not bound to an address space.
* @retval -EINVAL if attempting to use kernel mode submit in a safety build.
* @retval -EINVAL if num_gpfifo_entries in #args is greater than 2^31.
* @retval -EEXIST if gpfifo has already been allocated for this channel.
* @retval -E2BIG if there is no space available to append channel to runlist.
* @retval -ETIMEDOUT if runlist update timed out.
*/
int nvgpu_channel_setup_bind(struct nvgpu_channel *c,
struct nvgpu_setup_bind_args *args);
/**
* @brief Add/remove channel to/from runlist.
*
* @param ch [in] Channel pointer (must be non-NULL).
* @param add [in] True to add a channel, false to remove it.
*
* When \a add is true, adds \a c to runlist.
* When \a add is false, removes \a c from runlist.
*
* Function waits until H/W is done transitionning to the new runlist.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -E2BIG in case there are not enough entries in runlist buffer to
* accommodate all active channels/TSGs.
* @retval -ETIMEDOUT if runlist update timedout.
*/
int nvgpu_channel_update_runlist(struct nvgpu_channel *c, bool add);
/**
* @brief Wait until atomic counter is equal to N.
*
* @param ch [in] Channel pointer (must be non-NULL).
* @param counter [in] The counter to check.
* @param wait_value [in] The target value for the counter.
* @param c [in] The condition variable to sleep on. This
* condition variable is typically signaled
* by the thread which updates the counter.
* @param caller_name [in] Function name of caller.
* @param counter_name [in] Counter name.
*
* Waits until an atomic counter is equal to N.
* It is typically used to check the number of references on a channel.
* While waiting on the counter to reach N, periodic warnings are thrown with
* current and expected counter values.
*
* @note There is no timeout for this function. It will wait indefinitely
* until counter is equal to N.
*/
void nvgpu_channel_wait_until_counter_is_N(
struct nvgpu_channel *ch, nvgpu_atomic_t *counter, int wait_value,
struct nvgpu_cond *c, const char *caller, const char *counter_name);
/**
* @brief Free channel's usermode buffers.
*
* @param ch [in] Channel pointer (must be non-NULL).
*
* Frees userspace-managed userd and gpfifo buffers.
*/
void nvgpu_channel_free_usermode_buffers(struct nvgpu_channel *c);
/**
* @brief Size of a gpfifo entry
*
* @return Size of a gpfifo entry in bytes.
*/
static inline u32 nvgpu_get_gpfifo_entry_size(void)
{
return sizeof(struct nvgpu_gpfifo_entry);
}
#ifdef CONFIG_DEBUG_FS
void trace_write_pushbuffers(struct nvgpu_channel *c, u32 count);
#else
static inline void trace_write_pushbuffers(struct nvgpu_channel *c, u32 count)
{
(void)c;
(void)count;
}
#endif
/**
* @brief Mark channel as unserviceable.
*
* @param ch [in] Channel pointer.
*
* Once unserviceable, it is not possible to take extra references to
* the channel.
*/
void nvgpu_channel_set_unserviceable(struct nvgpu_channel *ch);
/**
* @brief Check if channel is unserviceable
*
* @param ch [in] Channel pointer.
*
* @return True if channel is unserviceable, false otherwise.
*/
bool nvgpu_channel_check_unserviceable(struct nvgpu_channel *ch);
/**
* @brief Signal on wait queues (notify_wq and semaphore_wq).
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
*
* Unblock pending waits on this channel (semaphore and error
* notifier wait queues).
*
*/
void nvgpu_channel_wakeup_wqs(struct gk20a *g, struct nvgpu_channel *ch);
#ifdef CONFIG_NVGPU_USERD
/**
* @brief Channel userd physical address.
*
* @param ch [in] Channel pointer.
*
* @return Physical address of channel's userd region.
*/
static inline u64 nvgpu_channel_userd_addr(struct nvgpu_channel *ch)
{
return nvgpu_mem_get_addr(ch->g, ch->userd_mem) + ch->userd_offset;
}
/**
* @brief Channel userd GPU VA.
*
* @param c [in] Channel pointer.
*
* @return GPU virtual address of channel's userd region, or
* 0ULL if not mapped.
*/
static inline u64 nvgpu_channel_userd_gpu_va(struct nvgpu_channel *c)
{
struct nvgpu_mem *mem = c->userd_mem;
return (mem->gpu_va != 0ULL) ? mem->gpu_va + c->userd_offset : 0ULL;
}
#endif
/**
* @brief Allocate channel instance block.
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
*
* Instance block is allocated in vidmem if supported by GPU,
* sysmem otherwise.
*
* @return 0 in case of success, < 0 in case of failure.
* @retval -ENOMEM in case there is not enough memory.
*/
int nvgpu_channel_alloc_inst(struct gk20a *g, struct nvgpu_channel *ch);
/**
* @brief Free channel instance block.
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
*/
void nvgpu_channel_free_inst(struct gk20a *g, struct nvgpu_channel *ch);
/**
* @brief Set error notifier.
*
* @param g [in] Pointer to GPU driver struct.
* @param ch [in] Channel pointer.
* @param error_notifier [in] Error notifier code.
*
* If an application has installed an error notifier buffer with
* #NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER, this function updates
* the buffer with a timestamp and #error_notifier for the error code (e.g.
* #NVGPU_ERR_NOTIFIER_FIFO_ERROR_MMU_ERR_FLT).
*
* @note This function does not wake up the notifer_wq.
*/
void nvgpu_channel_set_error_notifier(struct gk20a *g, struct nvgpu_channel *ch,
u32 error_notifier);
/**
* @brief Get channel from instance block.
*
* @param g [in] Pointer to GPU driver struct.
* @param inst_ptr [in] Instance block physical address.
*
* Search for the channel which instance block physical address is
* equal to #inst_ptr. If channel is found, an extra reference is
* taken on the channel, and should be released with #nvgpu_channel_put.
*
* @return Pointer to channel, or NULL if channel was not found.
*/
struct nvgpu_channel *nvgpu_channel_refch_from_inst_ptr(struct gk20a *g,
u64 inst_ptr);
/**
* @brief Dump debug information for all channels.
*
* @param g [in] Pointer to GPU driver struct.
* @param o [in] Debug context (which provides methods to
* output data).
*
* Dump human-readeable information about active channels.
*/
void nvgpu_channel_debug_dump_all(struct gk20a *g,
struct nvgpu_debug_context *o);
#ifdef CONFIG_NVGPU_DEBUGGER
int nvgpu_channel_deferred_reset_engines(struct gk20a *g,
struct nvgpu_channel *ch);
#endif
#ifdef CONFIG_NVGPU_CHANNEL_WDT
/**
* @brief Rewind the timeout on each non-dormant channel.
*
* Reschedule the timeout of each active channel for which timeouts are running
* as if something was happened on each channel right now. This should be
* called when a global hang is detected that could cause a false positive on
* other innocent channels.
*/
void nvgpu_channel_restart_all_wdts(struct gk20a *g);
/**
* @brief Enable or disable full debug dump on wdt error.
*
* Set the policy on whether or not to do the verbose channel and gr debug dump
* when the channel gets recovered as a result of a watchdog timeout.
*/
void nvgpu_channel_set_wdt_debug_dump(struct nvgpu_channel *ch, bool dump);
#else
static inline void nvgpu_channel_restart_all_wdts(struct gk20a *g)
{
(void)g;
}
static inline void nvgpu_channel_set_wdt_debug_dump(struct nvgpu_channel *ch,
bool dump)
{
(void)ch;
(void)dump;
}
#endif
/**
* @brief Get maximum sub context count.
*
* @param ch [in] Channel pointer.
*/
u32 nvgpu_channel_get_max_subctx_count(struct nvgpu_channel *ch);
#endif