| #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 |