mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 09:57:08 +03:00
The mechanism of posting events to userspace is OS specific. In linux this works through poll fd, wherein we can make use of nvgpu_cond variables to poll and trigger the corresponding wait_queue. The post event functionality on QNX doesn't work on poll though. It uses iofunc_notify_trigger to post the events to the calling process. As such QNX can't work with nvgpu_cond's. To overcome this issue, it is proposed to create OS specific interface function for posting clk arb events. Linux can call nvgpu_cond based implementation, which makes sense since these are already initialized and poll'ed in Linux specific code only. QNX can implement this interface to call iofunc_notify_* functions, as per its need. Jira VQRM-3741 Change-Id: I7d9f71dae2ae7f6a09cd56662003fd1b7e50324c Signed-off-by: Sourab Gupta <sourabg@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1709656 GVS: Gerrit_Virtual_Submit Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
360 lines
9.8 KiB
C
360 lines
9.8 KiB
C
/*
|
|
* Copyright (c) 2016-2018, 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_CLK_ARB_H__
|
|
#define __NVGPU_CLK_ARB_H__
|
|
|
|
#include <nvgpu/types.h>
|
|
#include <nvgpu/bitops.h>
|
|
#include <nvgpu/lock.h>
|
|
#include <nvgpu/kmem.h>
|
|
#include <nvgpu/atomic.h>
|
|
#include <nvgpu/bug.h>
|
|
#include <nvgpu/kref.h>
|
|
#include <nvgpu/log.h>
|
|
#include <nvgpu/barrier.h>
|
|
#include <nvgpu/cond.h>
|
|
|
|
#include "gk20a/gk20a.h"
|
|
#include "clk/clk.h"
|
|
#include "pstate/pstate.h"
|
|
#include "lpwr/lpwr.h"
|
|
#include "volt/volt.h"
|
|
|
|
#define MAX_F_POINTS 256
|
|
#define DEFAULT_EVENT_NUMBER 32
|
|
|
|
struct nvgpu_clk_dev;
|
|
struct nvgpu_clk_arb_target;
|
|
struct nvgpu_clk_notification_queue;
|
|
struct nvgpu_clk_session;
|
|
|
|
#define VF_POINT_INVALID_PSTATE ~0U
|
|
#define VF_POINT_SET_PSTATE_SUPPORTED(a, b) ((a)->pstates |= (1UL << (b)))
|
|
#define VF_POINT_GET_PSTATE(a) (((a)->pstates) ?\
|
|
__fls((a)->pstates) :\
|
|
VF_POINT_INVALID_PSTATE)
|
|
#define VF_POINT_COMMON_PSTATE(a, b) (((a)->pstates & (b)->pstates) ?\
|
|
__fls((a)->pstates & (b)->pstates) :\
|
|
VF_POINT_INVALID_PSTATE)
|
|
|
|
/*
|
|
* These events, defined in common code are the counterparts of the uapi
|
|
* events. There should be a conversion function to take care to convert
|
|
* these to the uapi events.
|
|
*/
|
|
/* Event associated to a VF update */
|
|
#define NVGPU_EVENT_VF_UPDATE 0
|
|
|
|
/* Recoverable alarms (POLLPRI) */
|
|
/* Alarm when target frequency on any session is not possible */
|
|
#define NVGPU_EVENT_ALARM_TARGET_VF_NOT_POSSIBLE 1
|
|
/* Alarm when target frequency on current session is not possible */
|
|
#define NVGPU_EVENT_ALARM_LOCAL_TARGET_VF_NOT_POSSIBLE 2
|
|
/* Alarm when Clock Arbiter failed */
|
|
#define NVGPU_EVENT_ALARM_CLOCK_ARBITER_FAILED 3
|
|
/* Alarm when VF table update failed */
|
|
#define NVGPU_EVENT_ALARM_VF_TABLE_UPDATE_FAILED 4
|
|
/* Alarm on thermal condition */
|
|
#define NVGPU_EVENT_ALARM_THERMAL_ABOVE_THRESHOLD 5
|
|
/* Alarm on power condition */
|
|
#define NVGPU_EVENT_ALARM_POWER_ABOVE_THRESHOLD 6
|
|
|
|
/* Non recoverable alarm (POLLHUP) */
|
|
/* Alarm on GPU shutdown/fall from bus */
|
|
#define NVGPU_EVENT_ALARM_GPU_LOST 7
|
|
|
|
#define NVGPU_EVENT_LAST NVGPU_EVENT_ALARM_GPU_LOST
|
|
|
|
/* Local Alarms */
|
|
#define EVENT(alarm) (0x1UL << NVGPU_EVENT_##alarm)
|
|
|
|
#define LOCAL_ALARM_MASK (EVENT(ALARM_LOCAL_TARGET_VF_NOT_POSSIBLE) | \
|
|
EVENT(VF_UPDATE))
|
|
|
|
#define _WRAPGTEQ(a, b) ((a-b) > 0)
|
|
|
|
/*
|
|
* NVGPU_POLL* defines equivalent to the POLL* linux defines
|
|
*/
|
|
#define NVGPU_POLLIN (1 << 0)
|
|
#define NVGPU_POLLPRI (1 << 1)
|
|
#define NVGPU_POLLOUT (1 << 2)
|
|
#define NVGPU_POLLRDNORM (1 << 3)
|
|
#define NVGPU_POLLHUP (1 << 4)
|
|
|
|
/* NVGPU_CLK_DOMAIN_* defines equivalent to NVGPU_GPU_CLK_DOMAIN_*
|
|
* defines in uapi header
|
|
*/
|
|
/* Memory clock */
|
|
#define NVGPU_CLK_DOMAIN_MCLK (0)
|
|
/* Main graphics core clock */
|
|
#define NVGPU_CLK_DOMAIN_GPCCLK (1)
|
|
|
|
#define NVGPU_CLK_DOMAIN_MAX (NVGPU_CLK_DOMAIN_GPCCLK)
|
|
|
|
#define clk_arb_dbg(g, fmt, args...) \
|
|
do { \
|
|
nvgpu_log(g, gpu_dbg_clk_arb, \
|
|
fmt, ##args); \
|
|
} while (0)
|
|
|
|
struct nvgpu_clk_notification {
|
|
u32 notification;
|
|
u64 timestamp;
|
|
};
|
|
|
|
struct nvgpu_clk_notification_queue {
|
|
u32 size;
|
|
nvgpu_atomic_t head;
|
|
nvgpu_atomic_t tail;
|
|
struct nvgpu_clk_notification *notifications;
|
|
};
|
|
|
|
struct nvgpu_clk_vf_point {
|
|
u16 pstates;
|
|
union {
|
|
struct {
|
|
u16 gpc_mhz;
|
|
u16 sys_mhz;
|
|
u16 xbar_mhz;
|
|
};
|
|
u16 mem_mhz;
|
|
};
|
|
u32 uvolt;
|
|
u32 uvolt_sram;
|
|
};
|
|
|
|
struct nvgpu_clk_vf_table {
|
|
u32 mclk_num_points;
|
|
struct nvgpu_clk_vf_point *mclk_points;
|
|
u32 gpc2clk_num_points;
|
|
struct nvgpu_clk_vf_point *gpc2clk_points;
|
|
};
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct nvgpu_clk_arb_debug {
|
|
s64 switch_max;
|
|
s64 switch_min;
|
|
u64 switch_num;
|
|
s64 switch_avg;
|
|
s64 switch_std;
|
|
};
|
|
#endif
|
|
|
|
struct nvgpu_clk_arb_target {
|
|
u16 mclk;
|
|
u16 gpc2clk;
|
|
u32 pstate;
|
|
};
|
|
|
|
enum clk_arb_work_item_type {
|
|
CLK_ARB_WORK_UPDATE_VF_TABLE,
|
|
CLK_ARB_WORK_UPDATE_ARB
|
|
};
|
|
|
|
struct nvgpu_clk_arb_work_item {
|
|
enum clk_arb_work_item_type item_type;
|
|
struct nvgpu_clk_arb *arb;
|
|
struct nvgpu_list_node worker_item;
|
|
};
|
|
|
|
struct nvgpu_clk_arb {
|
|
struct nvgpu_spinlock sessions_lock;
|
|
struct nvgpu_spinlock users_lock;
|
|
struct nvgpu_spinlock requests_lock;
|
|
|
|
struct nvgpu_mutex pstate_lock;
|
|
struct nvgpu_list_node users;
|
|
struct nvgpu_list_node sessions;
|
|
struct nvgpu_list_node requests;
|
|
|
|
struct gk20a *g;
|
|
int status;
|
|
|
|
struct nvgpu_clk_arb_target actual_pool[2];
|
|
struct nvgpu_clk_arb_target *actual;
|
|
|
|
u16 gpc2clk_default_mhz;
|
|
u16 mclk_default_mhz;
|
|
u32 voltuv_actual;
|
|
|
|
u16 gpc2clk_min, gpc2clk_max;
|
|
u16 mclk_min, mclk_max;
|
|
|
|
struct nvgpu_clk_arb_work_item update_vf_table_work_item;
|
|
struct nvgpu_clk_arb_work_item update_arb_work_item;
|
|
|
|
struct nvgpu_cond request_wq;
|
|
|
|
struct nvgpu_clk_vf_table *current_vf_table;
|
|
struct nvgpu_clk_vf_table vf_table_pool[2];
|
|
u32 vf_table_index;
|
|
|
|
u16 *mclk_f_points;
|
|
nvgpu_atomic_t req_nr;
|
|
|
|
u32 mclk_f_numpoints;
|
|
u16 *gpc2clk_f_points;
|
|
u32 gpc2clk_f_numpoints;
|
|
|
|
nvgpu_atomic64_t alarm_mask;
|
|
struct nvgpu_clk_notification_queue notification_queue;
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
struct nvgpu_clk_arb_debug debug_pool[2];
|
|
struct nvgpu_clk_arb_debug *debug;
|
|
bool debugfs_set;
|
|
#endif
|
|
};
|
|
|
|
struct nvgpu_clk_dev {
|
|
struct nvgpu_clk_session *session;
|
|
union {
|
|
struct nvgpu_list_node link;
|
|
struct nvgpu_list_node node;
|
|
};
|
|
struct nvgpu_cond readout_wq;
|
|
nvgpu_atomic_t poll_mask;
|
|
u16 gpc2clk_target_mhz;
|
|
u16 mclk_target_mhz;
|
|
u32 alarms_reported;
|
|
nvgpu_atomic_t enabled_mask;
|
|
struct nvgpu_clk_notification_queue queue;
|
|
u32 arb_queue_head;
|
|
struct nvgpu_ref refcount;
|
|
};
|
|
|
|
struct nvgpu_clk_session {
|
|
bool zombie;
|
|
struct gk20a *g;
|
|
struct nvgpu_ref refcount;
|
|
struct nvgpu_list_node link;
|
|
struct nvgpu_list_node targets;
|
|
|
|
struct nvgpu_spinlock session_lock;
|
|
struct nvgpu_clk_arb_target target_pool[2];
|
|
struct nvgpu_clk_arb_target *target;
|
|
};
|
|
|
|
static inline struct nvgpu_clk_session *
|
|
nvgpu_clk_session_from_link(struct nvgpu_list_node *node)
|
|
{
|
|
return (struct nvgpu_clk_session *)
|
|
((uintptr_t)node - offsetof(struct nvgpu_clk_session, link));
|
|
};
|
|
|
|
static inline struct nvgpu_clk_dev *
|
|
nvgpu_clk_dev_from_node(struct nvgpu_list_node *node)
|
|
{
|
|
return (struct nvgpu_clk_dev *)
|
|
((uintptr_t)node - offsetof(struct nvgpu_clk_dev, node));
|
|
};
|
|
|
|
static inline struct nvgpu_clk_dev *
|
|
nvgpu_clk_dev_from_link(struct nvgpu_list_node *node)
|
|
{
|
|
return (struct nvgpu_clk_dev *)
|
|
((uintptr_t)node - offsetof(struct nvgpu_clk_dev, link));
|
|
};
|
|
|
|
static inline struct nvgpu_clk_arb_work_item *
|
|
nvgpu_clk_arb_work_item_from_worker_item(struct nvgpu_list_node *node)
|
|
{
|
|
return (struct nvgpu_clk_arb_work_item *)
|
|
((uintptr_t)node - offsetof(struct nvgpu_clk_arb_work_item, worker_item));
|
|
};
|
|
|
|
void nvgpu_clk_arb_worker_enqueue(struct gk20a *g,
|
|
struct nvgpu_clk_arb_work_item *work_item);
|
|
|
|
int nvgpu_clk_arb_init_arbiter(struct gk20a *g);
|
|
|
|
int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain,
|
|
u16 *min_mhz, u16 *max_mhz);
|
|
|
|
int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g,
|
|
u32 api_domain, u16 *actual_mhz);
|
|
|
|
int nvgpu_clk_arb_get_arbiter_effective_mhz(struct gk20a *g,
|
|
u32 api_domain, u16 *effective_mhz);
|
|
|
|
int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g,
|
|
u32 api_domain, u32 *max_points, u16 *fpoints);
|
|
|
|
u32 nvgpu_clk_arb_get_arbiter_clk_domains(struct gk20a *g);
|
|
bool nvgpu_clk_arb_is_valid_domain(struct gk20a *g, u32 api_domain);
|
|
|
|
void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g);
|
|
|
|
int nvgpu_clk_arb_install_session_fd(struct gk20a *g,
|
|
struct nvgpu_clk_session *session);
|
|
|
|
int nvgpu_clk_arb_init_session(struct gk20a *g,
|
|
struct nvgpu_clk_session **_session);
|
|
|
|
void nvgpu_clk_arb_release_session(struct gk20a *g,
|
|
struct nvgpu_clk_session *session);
|
|
|
|
int nvgpu_clk_arb_commit_request_fd(struct gk20a *g,
|
|
struct nvgpu_clk_session *session, int request_fd);
|
|
|
|
int nvgpu_clk_arb_set_session_target_mhz(struct nvgpu_clk_session *session,
|
|
int fd, u32 api_domain, u16 target_mhz);
|
|
|
|
int nvgpu_clk_arb_get_session_target_mhz(struct nvgpu_clk_session *session,
|
|
u32 api_domain, u16 *target_mhz);
|
|
|
|
int nvgpu_clk_arb_install_event_fd(struct gk20a *g,
|
|
struct nvgpu_clk_session *session, int *event_fd, u32 alarm_mask);
|
|
|
|
int nvgpu_clk_arb_install_request_fd(struct gk20a *g,
|
|
struct nvgpu_clk_session *session, int *event_fd);
|
|
|
|
void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g);
|
|
|
|
int nvgpu_clk_arb_get_current_pstate(struct gk20a *g);
|
|
|
|
void nvgpu_clk_arb_pstate_change_lock(struct gk20a *g, bool lock);
|
|
|
|
void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g);
|
|
|
|
void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm);
|
|
|
|
void nvgpu_clk_arb_free_session(struct nvgpu_ref *refcount);
|
|
|
|
void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount);
|
|
|
|
int nvgpu_clk_notification_queue_alloc(struct gk20a *g,
|
|
struct nvgpu_clk_notification_queue *queue,
|
|
size_t events_number);
|
|
|
|
void nvgpu_clk_notification_queue_free(struct gk20a *g,
|
|
struct nvgpu_clk_notification_queue *queue);
|
|
|
|
void nvgpu_clk_arb_event_post_event(struct nvgpu_clk_dev *dev);
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
int nvgpu_clk_arb_debugfs_init(struct gk20a *g);
|
|
#endif
|
|
#endif /* __NVGPU_CLK_ARB_H__ */
|
|
|