mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-21 06:50:25 +00:00

This commit adds support for the GB20x GPUs found on GeForce RTX 50xx series boards. Beyond a few miscellaneous register moves and HW class ID plumbing, this reuses most of the code added to support GH100/GB10x. Signed-off-by: Ben Skeggs <bskeggs@nvidia.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Timur Tabi <ttabi@nvidia.com> Tested-by: Timur Tabi <ttabi@nvidia.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
497 lines
11 KiB
C
497 lines
11 KiB
C
#ifndef __NVKM_GSP_H__
|
|
#define __NVKM_GSP_H__
|
|
#define nvkm_gsp(p) container_of((p), struct nvkm_gsp, subdev)
|
|
#include <core/subdev.h>
|
|
#include <core/falcon.h>
|
|
#include <core/firmware.h>
|
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#define GSP_PAGE_SHIFT 12
|
|
#define GSP_PAGE_SIZE BIT(GSP_PAGE_SHIFT)
|
|
|
|
struct nvkm_gsp_mem {
|
|
struct device *dev;
|
|
size_t size;
|
|
void *data;
|
|
dma_addr_t addr;
|
|
};
|
|
|
|
int nvkm_gsp_mem_ctor(struct nvkm_gsp *, size_t size, struct nvkm_gsp_mem *);
|
|
void nvkm_gsp_mem_dtor(struct nvkm_gsp_mem *);
|
|
|
|
struct nvkm_gsp_radix3 {
|
|
struct nvkm_gsp_mem lvl0;
|
|
struct nvkm_gsp_mem lvl1;
|
|
struct sg_table lvl2;
|
|
};
|
|
|
|
int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
|
|
void nvkm_gsp_sg_free(struct nvkm_device *, struct sg_table *);
|
|
|
|
typedef int (*nvkm_gsp_msg_ntfy_func)(void *priv, u32 fn, void *repv, u32 repc);
|
|
|
|
struct nvkm_gsp_event;
|
|
typedef void (*nvkm_gsp_event_func)(struct nvkm_gsp_event *, void *repv, u32 repc);
|
|
|
|
/**
|
|
* DOC: GSP message handling policy
|
|
*
|
|
* When sending a GSP RPC command, there can be multiple cases of handling
|
|
* the GSP RPC messages, which are the reply of GSP RPC commands, according
|
|
* to the requirement of the callers and the nature of the GSP RPC commands.
|
|
*
|
|
* NVKM_GSP_RPC_REPLY_NOWAIT - If specified, immediately return to the
|
|
* caller after the GSP RPC command is issued.
|
|
*
|
|
* NVKM_GSP_RPC_REPLY_RECV - If specified, wait and receive the entire GSP
|
|
* RPC message after the GSP RPC command is issued.
|
|
*
|
|
* NVKM_GSP_RPC_REPLY_POLL - If specified, wait for the specific reply and
|
|
* discard the reply before returning to the caller.
|
|
*
|
|
*/
|
|
enum nvkm_gsp_rpc_reply_policy {
|
|
NVKM_GSP_RPC_REPLY_NOWAIT = 0,
|
|
NVKM_GSP_RPC_REPLY_RECV,
|
|
NVKM_GSP_RPC_REPLY_POLL,
|
|
};
|
|
|
|
struct nvkm_gsp {
|
|
const struct nvkm_gsp_func *func;
|
|
struct nvkm_subdev subdev;
|
|
|
|
struct nvkm_falcon falcon;
|
|
|
|
struct {
|
|
struct {
|
|
const struct firmware *load;
|
|
const struct firmware *unload;
|
|
} booter;
|
|
|
|
const struct firmware *fmc;
|
|
|
|
const struct firmware *bl;
|
|
const struct firmware *rm;
|
|
} fws;
|
|
|
|
struct nvkm_firmware fw;
|
|
struct nvkm_gsp_mem sig;
|
|
struct nvkm_gsp_radix3 radix3;
|
|
|
|
struct {
|
|
struct {
|
|
struct {
|
|
u64 addr;
|
|
u64 size;
|
|
} vga_workspace;
|
|
u64 addr;
|
|
u64 size;
|
|
} bios;
|
|
struct {
|
|
struct {
|
|
u64 addr;
|
|
u64 size;
|
|
} frts, boot, elf, heap;
|
|
u64 addr;
|
|
u64 size;
|
|
} wpr2;
|
|
struct {
|
|
u64 addr;
|
|
u64 size;
|
|
} heap;
|
|
u64 addr;
|
|
u64 size;
|
|
|
|
struct {
|
|
u64 addr;
|
|
u64 size;
|
|
} region[16];
|
|
int region_nr;
|
|
u32 rsvd_size;
|
|
} fb;
|
|
|
|
struct {
|
|
struct nvkm_falcon_fw load;
|
|
struct nvkm_falcon_fw unload;
|
|
} booter;
|
|
|
|
struct {
|
|
struct nvkm_gsp_mem fw;
|
|
u8 *hash;
|
|
u8 *pkey;
|
|
u8 *sig;
|
|
|
|
struct nvkm_gsp_mem args;
|
|
} fmc;
|
|
|
|
struct {
|
|
struct nvkm_gsp_mem fw;
|
|
u32 code_offset;
|
|
u32 data_offset;
|
|
u32 manifest_offset;
|
|
u32 app_version;
|
|
} boot;
|
|
|
|
struct nvkm_gsp_mem libos;
|
|
struct nvkm_gsp_mem loginit;
|
|
struct nvkm_gsp_mem logintr;
|
|
struct nvkm_gsp_mem logrm;
|
|
struct nvkm_gsp_mem rmargs;
|
|
|
|
struct nvkm_gsp_mem wpr_meta;
|
|
|
|
struct {
|
|
struct sg_table sgt;
|
|
struct nvkm_gsp_radix3 radix3;
|
|
struct nvkm_gsp_mem meta;
|
|
struct sg_table fbsr;
|
|
} sr;
|
|
|
|
struct {
|
|
struct nvkm_gsp_mem mem;
|
|
|
|
struct {
|
|
int nr;
|
|
u32 size;
|
|
u64 *ptr;
|
|
} ptes;
|
|
|
|
struct {
|
|
u32 size;
|
|
void *ptr;
|
|
} cmdq, msgq;
|
|
} shm;
|
|
|
|
struct nvkm_gsp_cmdq {
|
|
struct mutex mutex;
|
|
u32 cnt;
|
|
u32 seq;
|
|
u32 *wptr;
|
|
u32 *rptr;
|
|
} cmdq;
|
|
|
|
struct nvkm_gsp_msgq {
|
|
struct mutex mutex;
|
|
u32 cnt;
|
|
u32 *wptr;
|
|
u32 *rptr;
|
|
struct nvkm_gsp_msgq_ntfy {
|
|
u32 fn;
|
|
nvkm_gsp_msg_ntfy_func func;
|
|
void *priv;
|
|
} ntfy[16];
|
|
int ntfy_nr;
|
|
struct work_struct work;
|
|
} msgq;
|
|
|
|
bool running;
|
|
|
|
/* Internal GSP-RM control handles. */
|
|
struct {
|
|
struct nvkm_gsp_client {
|
|
struct nvkm_gsp_object {
|
|
struct nvkm_gsp_client *client;
|
|
struct nvkm_gsp_object *parent;
|
|
u32 handle;
|
|
} object;
|
|
|
|
struct nvkm_gsp *gsp;
|
|
|
|
struct list_head events;
|
|
} client;
|
|
|
|
struct nvkm_gsp_device {
|
|
struct nvkm_gsp_object object;
|
|
struct nvkm_gsp_object subdevice;
|
|
} device;
|
|
} internal;
|
|
|
|
struct {
|
|
enum nvkm_subdev_type type;
|
|
int inst;
|
|
u32 stall;
|
|
u32 nonstall;
|
|
} intr[32];
|
|
int intr_nr;
|
|
|
|
struct {
|
|
u64 rm_bar1_pdb;
|
|
u64 rm_bar2_pdb;
|
|
} bar;
|
|
|
|
struct {
|
|
u8 gpcs;
|
|
u8 tpcs;
|
|
} gr;
|
|
|
|
struct nvkm_rm *rm;
|
|
|
|
struct {
|
|
struct mutex mutex;
|
|
struct idr idr;
|
|
} client_id;
|
|
|
|
/* A linked list of registry items. The registry RPC will be built from it. */
|
|
struct list_head registry_list;
|
|
|
|
/* The size of the registry RPC */
|
|
size_t registry_rpc_size;
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
/*
|
|
* Logging buffers in debugfs. The wrapper objects need to remain
|
|
* in memory until the dentry is deleted.
|
|
*/
|
|
struct {
|
|
struct dentry *parent;
|
|
struct dentry *init;
|
|
struct dentry *rm;
|
|
struct dentry *intr;
|
|
struct dentry *pmu;
|
|
} debugfs;
|
|
struct debugfs_blob_wrapper blob_init;
|
|
struct debugfs_blob_wrapper blob_intr;
|
|
struct debugfs_blob_wrapper blob_rm;
|
|
struct debugfs_blob_wrapper blob_pmu;
|
|
#endif
|
|
};
|
|
|
|
static inline bool
|
|
nvkm_gsp_rm(struct nvkm_gsp *gsp)
|
|
{
|
|
return gsp && (gsp->fws.rm || gsp->fw.img);
|
|
}
|
|
|
|
#include <rm/rm.h>
|
|
|
|
static inline void *
|
|
nvkm_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc)
|
|
{
|
|
return gsp->rm->api->rpc->get(gsp, fn, argc);
|
|
}
|
|
|
|
static inline void *
|
|
nvkm_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv,
|
|
enum nvkm_gsp_rpc_reply_policy policy, u32 repc)
|
|
{
|
|
return gsp->rm->api->rpc->push(gsp, argv, policy, repc);
|
|
}
|
|
|
|
static inline void *
|
|
nvkm_gsp_rpc_rd(struct nvkm_gsp *gsp, u32 fn, u32 argc)
|
|
{
|
|
void *argv = nvkm_gsp_rpc_get(gsp, fn, argc);
|
|
|
|
if (IS_ERR_OR_NULL(argv))
|
|
return argv;
|
|
|
|
return nvkm_gsp_rpc_push(gsp, argv, NVKM_GSP_RPC_REPLY_RECV, argc);
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_rpc_wr(struct nvkm_gsp *gsp, void *argv,
|
|
enum nvkm_gsp_rpc_reply_policy policy)
|
|
{
|
|
void *repv = nvkm_gsp_rpc_push(gsp, argv, policy, 0);
|
|
|
|
if (IS_ERR(repv))
|
|
return PTR_ERR(repv);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void
|
|
nvkm_gsp_rpc_done(struct nvkm_gsp *gsp, void *repv)
|
|
{
|
|
gsp->rm->api->rpc->done(gsp, repv);
|
|
}
|
|
|
|
static inline void *
|
|
nvkm_gsp_rm_ctrl_get(struct nvkm_gsp_object *object, u32 cmd, u32 argc)
|
|
{
|
|
return object->client->gsp->rm->api->ctrl->get(object, cmd, argc);
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_rm_ctrl_push(struct nvkm_gsp_object *object, void *argv, u32 repc)
|
|
{
|
|
return object->client->gsp->rm->api->ctrl->push(object, argv, repc);
|
|
}
|
|
|
|
static inline void *
|
|
nvkm_gsp_rm_ctrl_rd(struct nvkm_gsp_object *object, u32 cmd, u32 repc)
|
|
{
|
|
void *argv = nvkm_gsp_rm_ctrl_get(object, cmd, repc);
|
|
int ret;
|
|
|
|
if (IS_ERR(argv))
|
|
return argv;
|
|
|
|
ret = nvkm_gsp_rm_ctrl_push(object, &argv, repc);
|
|
if (ret)
|
|
return ERR_PTR(ret);
|
|
return argv;
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_rm_ctrl_wr(struct nvkm_gsp_object *object, void *argv)
|
|
{
|
|
int ret = nvkm_gsp_rm_ctrl_push(object, &argv, 0);
|
|
|
|
if (ret)
|
|
return ret;
|
|
return 0;
|
|
}
|
|
|
|
static inline void
|
|
nvkm_gsp_rm_ctrl_done(struct nvkm_gsp_object *object, void *repv)
|
|
{
|
|
object->client->gsp->rm->api->ctrl->done(object, repv);
|
|
}
|
|
|
|
static inline void *
|
|
nvkm_gsp_rm_alloc_get(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u32 argc,
|
|
struct nvkm_gsp_object *object)
|
|
{
|
|
struct nvkm_gsp_client *client = parent->client;
|
|
struct nvkm_gsp *gsp = client->gsp;
|
|
void *argv;
|
|
|
|
object->client = parent->client;
|
|
object->parent = parent;
|
|
object->handle = handle;
|
|
|
|
argv = gsp->rm->api->alloc->get(object, oclass, argc);
|
|
if (IS_ERR_OR_NULL(argv)) {
|
|
object->client = NULL;
|
|
return argv;
|
|
}
|
|
|
|
return argv;
|
|
}
|
|
|
|
static inline void *
|
|
nvkm_gsp_rm_alloc_push(struct nvkm_gsp_object *object, void *argv)
|
|
{
|
|
void *repv = object->client->gsp->rm->api->alloc->push(object, argv);
|
|
|
|
if (IS_ERR(repv))
|
|
object->client = NULL;
|
|
|
|
return repv;
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_rm_alloc_wr(struct nvkm_gsp_object *object, void *argv)
|
|
{
|
|
void *repv = nvkm_gsp_rm_alloc_push(object, argv);
|
|
|
|
if (IS_ERR(repv))
|
|
return PTR_ERR(repv);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void
|
|
nvkm_gsp_rm_alloc_done(struct nvkm_gsp_object *object, void *repv)
|
|
{
|
|
object->client->gsp->rm->api->alloc->done(object, repv);
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_rm_alloc(struct nvkm_gsp_object *parent, u32 handle, u32 oclass, u32 argc,
|
|
struct nvkm_gsp_object *object)
|
|
{
|
|
void *argv = nvkm_gsp_rm_alloc_get(parent, handle, oclass, argc, object);
|
|
|
|
if (IS_ERR_OR_NULL(argv))
|
|
return argv ? PTR_ERR(argv) : -EIO;
|
|
|
|
return nvkm_gsp_rm_alloc_wr(object, argv);
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_rm_free(struct nvkm_gsp_object *object)
|
|
{
|
|
if (object->client) {
|
|
int ret = object->client->gsp->rm->api->alloc->free(object);
|
|
object->client = NULL;
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int nvkm_gsp_client_ctor(struct nvkm_gsp *, struct nvkm_gsp_client *);
|
|
void nvkm_gsp_client_dtor(struct nvkm_gsp_client *);
|
|
|
|
static inline int
|
|
nvkm_gsp_device_ctor(struct nvkm_gsp_client *client, struct nvkm_gsp_device *device)
|
|
{
|
|
return client->gsp->rm->api->device->ctor(client, device);
|
|
}
|
|
|
|
static inline void
|
|
nvkm_gsp_device_dtor(struct nvkm_gsp_device *device)
|
|
{
|
|
if (device->object.client)
|
|
device->object.client->gsp->rm->api->device->dtor(device);
|
|
}
|
|
|
|
static inline int
|
|
nvkm_gsp_client_device_ctor(struct nvkm_gsp *gsp,
|
|
struct nvkm_gsp_client *client, struct nvkm_gsp_device *device)
|
|
{
|
|
int ret = nvkm_gsp_client_ctor(gsp, client);
|
|
|
|
if (ret == 0) {
|
|
ret = nvkm_gsp_device_ctor(client, device);
|
|
if (ret)
|
|
nvkm_gsp_client_dtor(client);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
struct nvkm_gsp_event {
|
|
struct nvkm_gsp_device *device;
|
|
u32 id;
|
|
nvkm_gsp_event_func func;
|
|
|
|
struct nvkm_gsp_object object;
|
|
|
|
struct list_head head;
|
|
};
|
|
|
|
static inline int
|
|
nvkm_gsp_device_event_ctor(struct nvkm_gsp_device *device, u32 handle, u32 id,
|
|
nvkm_gsp_event_func func, struct nvkm_gsp_event *event)
|
|
{
|
|
struct nvkm_rm *rm = device->object.client->gsp->rm;
|
|
|
|
return rm->api->device->event.ctor(device, handle, id, func, event);
|
|
}
|
|
|
|
static inline void
|
|
nvkm_gsp_event_dtor(struct nvkm_gsp_event *event)
|
|
{
|
|
struct nvkm_gsp_device *device = event->device;
|
|
|
|
if (device)
|
|
device->object.client->gsp->rm->api->device->event.dtor(event);
|
|
}
|
|
|
|
int nvkm_gsp_intr_stall(struct nvkm_gsp *, enum nvkm_subdev_type, int);
|
|
int nvkm_gsp_intr_nonstall(struct nvkm_gsp *, enum nvkm_subdev_type, int);
|
|
|
|
int gv100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int tu102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int tu116_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int ga100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int ga102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int gh100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int ad102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int gb100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
int gb202_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
|
|
#endif
|