#ifndef __NVKM_GSP_H__ #define __NVKM_GSP_H__ #define nvkm_gsp(p) container_of((p), struct nvkm_gsp, subdev) #include #include #include #define GSP_PAGE_SHIFT 12 #define GSP_PAGE_SIZE BIT(GSP_PAGE_SHIFT) struct nvkm_gsp_mem { u32 size; void *data; dma_addr_t addr; }; struct nvkm_gsp_radix3 { struct nvkm_gsp_mem mem[3]; }; 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); 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 *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; 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; } 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; const struct nvkm_gsp_rm { void *(*rpc_get)(struct nvkm_gsp *, u32 fn, u32 argc); void *(*rpc_push)(struct nvkm_gsp *, void *argv, bool wait, u32 repc); void (*rpc_done)(struct nvkm_gsp *gsp, void *repv); void *(*rm_ctrl_get)(struct nvkm_gsp_object *, u32 cmd, u32 argc); int (*rm_ctrl_push)(struct nvkm_gsp_object *, void **argv, u32 repc); void (*rm_ctrl_done)(struct nvkm_gsp_object *, void *repv); void *(*rm_alloc_get)(struct nvkm_gsp_object *, u32 oclass, u32 argc); void *(*rm_alloc_push)(struct nvkm_gsp_object *, void *argv, u32 repc); void (*rm_alloc_done)(struct nvkm_gsp_object *, void *repv); int (*rm_free)(struct nvkm_gsp_object *); int (*client_ctor)(struct nvkm_gsp *, struct nvkm_gsp_client *); void (*client_dtor)(struct nvkm_gsp_client *); int (*device_ctor)(struct nvkm_gsp_client *, struct nvkm_gsp_device *); void (*device_dtor)(struct nvkm_gsp_device *); int (*event_ctor)(struct nvkm_gsp_device *, u32 handle, u32 id, nvkm_gsp_event_func, struct nvkm_gsp_event *); void (*event_dtor)(struct nvkm_gsp_event *); } *rm; struct { struct mutex mutex;; struct idr idr; } client_id; }; static inline bool nvkm_gsp_rm(struct nvkm_gsp *gsp) { return gsp && (gsp->fws.rm || gsp->fw.img); } static inline void * nvkm_gsp_rpc_get(struct nvkm_gsp *gsp, u32 fn, u32 argc) { return gsp->rm->rpc_get(gsp, fn, argc); } static inline void * nvkm_gsp_rpc_push(struct nvkm_gsp *gsp, void *argv, bool wait, u32 repc) { return gsp->rm->rpc_push(gsp, argv, wait, 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, true, argc); } static inline int nvkm_gsp_rpc_wr(struct nvkm_gsp *gsp, void *argv, bool wait) { void *repv = nvkm_gsp_rpc_push(gsp, argv, wait, 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->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->rm_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->rm_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->rm_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->rm_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, u32 repc) { void *repv = object->client->gsp->rm->rm_alloc_push(object, argv, repc); 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, 0); 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->rm_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) return object->client->gsp->rm->rm_free(object); return 0; } static inline int nvkm_gsp_client_ctor(struct nvkm_gsp *gsp, struct nvkm_gsp_client *client) { if (WARN_ON(!gsp->rm)) return -ENOSYS; return gsp->rm->client_ctor(gsp, client); } static inline void nvkm_gsp_client_dtor(struct nvkm_gsp_client *client) { if (client->gsp) client->gsp->rm->client_dtor(client); } static inline int nvkm_gsp_device_ctor(struct nvkm_gsp_client *client, struct nvkm_gsp_device *device) { return client->gsp->rm->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->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) { return device->object.client->gsp->rm->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->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 ad102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **); #endif