[PATCH v2 21/62] drm/nouveau/gsp: use internal.{client, device, subdevice} where possible

Ben Skeggs bskeggs at nvidia.com
Sun May 11 21:06:41 UTC 2025


As nouveau never directly exposes RMAPI to userspace, there's no real
reason why we need to be creating client/device/subdevice objects for
every client.  Instead, use the object handles provided by GSP during
initialisation.

This prevents 4x RPCs to GSP every time the nouveau FD is opened.

Signed-off-by: Ben Skeggs <bskeggs at nvidia.com>
Reviewed-by: Dave Airlie <airlied at redhat.com>
Reviewed-by: Timur Tabi <ttabi at nvidia.com>
Tested-by: Timur Tabi <ttabi at nvidia.com>
---
 .../drm/nouveau/include/nvkm/engine/disp.h    |  3 --
 .../gpu/drm/nouveau/include/nvkm/subdev/mmu.h |  6 ++--
 .../gpu/drm/nouveau/nvkm/engine/disp/outp.c   |  2 +-
 .../gpu/drm/nouveau/nvkm/engine/disp/uconn.c  |  4 +--
 .../drm/nouveau/nvkm/subdev/gsp/rm/handles.h  |  2 +-
 .../nouveau/nvkm/subdev/gsp/rm/r535/disp.c    | 19 ++++-------
 .../nouveau/nvkm/subdev/gsp/rm/r535/fifo.c    |  8 ++---
 .../drm/nouveau/nvkm/subdev/gsp/rm/r535/gr.c  |  8 ++---
 .../drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c |  7 +++-
 .../drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c | 32 ++++++++++++++-----
 .../gpu/drm/nouveau/nvkm/subdev/mmu/base.c    |  1 +
 drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c |  7 ++--
 12 files changed, 58 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
index 7903d7470d19..48dc7ec42164 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
@@ -12,9 +12,6 @@ struct nvkm_disp {
 	struct nvkm_engine engine;
 
 	struct {
-		struct nvkm_gsp_client client;
-		struct nvkm_gsp_device device;
-
 		struct nvkm_gsp_object objcom;
 		struct nvkm_gsp_object object;
 
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
index 935b1cacd528..5320e15f4fc8 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
@@ -68,8 +68,6 @@ struct nvkm_vmm {
 	struct {
 		u64 bar2_pdb;
 
-		struct nvkm_gsp_client client;
-		struct nvkm_gsp_device device;
 		struct nvkm_gsp_object object;
 
 		struct nvkm_vma *rsvd;
@@ -148,6 +146,10 @@ struct nvkm_mmu {
 	struct mutex mutex; /* serialises mmu invalidations */
 
 	struct nvkm_device_oclass user;
+
+	struct {
+		struct ida vmm_ids;
+	} rm;
 };
 
 int nv04_mmu_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mmu **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
index 28adc5a30f2f..02de74b406a3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
@@ -386,7 +386,7 @@ nvkm_outp_new_(const struct nvkm_outp_func *func, struct nvkm_disp *disp,
 	outp->disp = disp;
 	outp->index = index;
 	outp->info = *dcbE;
-	if (!disp->rm.client.gsp)
+	if (!disp->rm.objcom.client)
 		outp->i2c = nvkm_i2c_bus_find(i2c, dcbE->i2c_index);
 
 	OUTP_DBG(outp, "type %02x loc %d or %d link %d con %x "
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
index 2dab6612c4fc..f9398c5576ff 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
@@ -102,7 +102,7 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
 	u64 bits = 0;
 
 	if (!uevent) {
-		if (!disp->rm.client.gsp && conn->info.hpd == DCB_GPIO_UNUSED)
+		if (!disp->rm.objcom.client && conn->info.hpd == DCB_GPIO_UNUSED)
 			return -ENOSYS;
 		return 0;
 	}
@@ -118,7 +118,7 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
 	if (&outp->head == &conn->disp->outps)
 		return -EINVAL;
 
-	if (disp->rm.client.gsp) {
+	if (disp->rm.objcom.client) {
 		if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_DPYID_PLUG;
 		if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_DPYID_UNPLUG;
 		if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ   ) bits |= NVKM_DPYID_IRQ;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/handles.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/handles.h
index 66604474e339..0308fb7b9647 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/handles.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/handles.h
@@ -11,7 +11,7 @@
 #define NVKM_RM_DEVICE              0xde1d0000
 #define NVKM_RM_SUBDEVICE           0x5d1d0000
 #define NVKM_RM_DISP                0x00730000
-#define NVKM_RM_VASPACE             0x90f10000
+#define NVKM_RM_VASPACE(id)        (0x90f10000 | (id))
 #define NVKM_RM_CHAN(chid)         (0xf1f00000 | (chid))
 #define NVKM_RM_THREED              0x97000000
 #define NVKM_RM_ENGOBJ(class,chid) (((class) << 16) | (chid))
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
index 1ba86e223978..ee4893e3c9b1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
@@ -150,7 +150,7 @@ r535_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 hand
 {
 	return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle,
 				 chan->chid.user << 25 |
-				 (chan->disp->rm.client.object.handle & 0x3fff));
+				 (chan->rm.object.client->object.handle & 0x3fff));
 }
 
 static void
@@ -1414,17 +1414,16 @@ r535_disp_fini(struct nvkm_disp *disp, bool suspend)
 		nvkm_event_fini(&disp->rm.event);
 
 		nvkm_gsp_rm_free(&disp->rm.objcom);
-		nvkm_gsp_device_dtor(&disp->rm.device);
-		nvkm_gsp_client_dtor(&disp->rm.client);
 	}
 }
 
 static int
 r535_disp_init(struct nvkm_disp *disp)
 {
+	struct nvkm_gsp *gsp = disp->engine.subdev.device->gsp;
 	int ret;
 
-	ret = nvkm_gsp_rm_alloc(&disp->rm.device.object, disp->func->root.oclass << 16,
+	ret = nvkm_gsp_rm_alloc(&gsp->internal.device.object, disp->func->root.oclass << 16,
 				disp->func->root.oclass, 0, &disp->rm.object);
 	if (ret)
 		return ret;
@@ -1464,11 +1463,7 @@ r535_disp_oneinit(struct nvkm_disp *disp)
 		return ret;
 
 	/* OBJs. */
-	ret = nvkm_gsp_client_device_ctor(gsp, &disp->rm.client, &disp->rm.device);
-	if (ret)
-		return ret;
-
-	ret = nvkm_gsp_rm_alloc(&disp->rm.device.object, NVKM_RM_DISP, NV04_DISPLAY_COMMON, 0,
+	ret = nvkm_gsp_rm_alloc(&gsp->internal.device.object, NVKM_RM_DISP, NV04_DISPLAY_COMMON, 0,
 				&disp->rm.objcom);
 	if (ret)
 		return ret;
@@ -1491,7 +1486,7 @@ r535_disp_oneinit(struct nvkm_disp *disp)
 	{
 #if defined(CONFIG_ACPI) && defined(CONFIG_X86)
 		NV2080_CTRL_INTERNAL_INIT_BRIGHTC_STATE_LOAD_PARAMS *ctrl;
-		struct nvkm_gsp_object *subdevice = &disp->rm.client.gsp->internal.device.subdevice;
+		struct nvkm_gsp_object *subdevice = &gsp->internal.device.subdevice;
 
 		ctrl = nvkm_gsp_rm_ctrl_get(subdevice,
 					    NV2080_CTRL_CMD_INTERNAL_INIT_BRIGHTC_STATE_LOAD,
@@ -1639,12 +1634,12 @@ r535_disp_oneinit(struct nvkm_disp *disp)
 	if (WARN_ON(ret))
 		return ret;
 
-	ret = nvkm_gsp_device_event_ctor(&disp->rm.device, 0x007e0000, NV2080_NOTIFIERS_HOTPLUG,
+	ret = nvkm_gsp_device_event_ctor(&gsp->internal.device, 0x007e0000, NV2080_NOTIFIERS_HOTPLUG,
 					 r535_disp_hpd, &disp->rm.hpd);
 	if (ret)
 		return ret;
 
-	ret = nvkm_gsp_device_event_ctor(&disp->rm.device, 0x007e0001, NV2080_NOTIFIERS_DP_IRQ,
+	ret = nvkm_gsp_device_event_ctor(&gsp->internal.device, 0x007e0001, NV2080_NOTIFIERS_DP_IRQ,
 					 r535_disp_irq, &disp->rm.irq);
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c
index 4353cd70811a..663e58b914cd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c
@@ -101,7 +101,7 @@ r535_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm,
 	if (!chan->rm.mthdbuf.ptr)
 		return -ENOMEM;
 
-	args = nvkm_gsp_rm_alloc_get(&chan->vmm->rm.device.object, NVKM_RM_CHAN(chan->id),
+	args = nvkm_gsp_rm_alloc_get(&device->gsp->internal.device.object, NVKM_RM_CHAN(chan->id),
 				     fifo->func->chan.user.oclass, sizeof(*args),
 				     &chan->rm.object);
 	if (WARN_ON(IS_ERR(args)))
@@ -373,10 +373,10 @@ r535_gr = {
 static int
 r535_flcn_bind(struct nvkm_engn *engn, struct nvkm_vctx *vctx, struct nvkm_chan *chan)
 {
-	struct nvkm_gsp_client *client = &chan->vmm->rm.client;
+	struct nvkm_gsp_client *client = chan->rm.object.client;
 	NV2080_CTRL_GPU_PROMOTE_CTX_PARAMS *ctrl;
 
-	ctrl = nvkm_gsp_rm_ctrl_get(&chan->vmm->rm.device.subdevice,
+	ctrl = nvkm_gsp_rm_ctrl_get(&client->gsp->internal.device.subdevice,
 				    NV2080_CTRL_CMD_GPU_PROMOTE_CTX, sizeof(*ctrl));
 	if (IS_ERR(ctrl))
 		return PTR_ERR(ctrl);
@@ -389,7 +389,7 @@ r535_flcn_bind(struct nvkm_engn *engn, struct nvkm_vctx *vctx, struct nvkm_chan
 	ctrl->engineType = engn->id;
 	ctrl->ChID = chan->id;
 
-	return nvkm_gsp_rm_ctrl_wr(&chan->vmm->rm.device.subdevice, ctrl);
+	return nvkm_gsp_rm_ctrl_wr(&client->gsp->internal.device.subdevice, ctrl);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gr.c
index 4c0df52e8683..d882a400aa88 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gr.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gr.c
@@ -64,13 +64,13 @@ r535_gr_promote_ctx(struct r535_gr *gr, bool golden, struct nvkm_vmm *vmm,
 	struct nvkm_device *device = subdev->device;
 	NV2080_CTRL_GPU_PROMOTE_CTX_PARAMS *ctrl;
 
-	ctrl = nvkm_gsp_rm_ctrl_get(&vmm->rm.device.subdevice,
+	ctrl = nvkm_gsp_rm_ctrl_get(&device->gsp->internal.device.subdevice,
 				    NV2080_CTRL_CMD_GPU_PROMOTE_CTX, sizeof(*ctrl));
 	if (WARN_ON(IS_ERR(ctrl)))
 		return PTR_ERR(ctrl);
 
 	ctrl->engineType = 1;
-	ctrl->hChanClient = vmm->rm.client.object.handle;
+	ctrl->hChanClient = chan->client->object.handle;
 	ctrl->hObject = chan->handle;
 
 	for (int i = 0; i < gr->ctxbuf_nr; i++) {
@@ -135,7 +135,7 @@ r535_gr_promote_ctx(struct r535_gr *gr, bool golden, struct nvkm_vmm *vmm,
 		ctrl->entryCount++;
 	}
 
-	return nvkm_gsp_rm_ctrl_wr(&vmm->rm.device.subdevice, ctrl);
+	return nvkm_gsp_rm_ctrl_wr(&device->gsp->internal.device.subdevice, ctrl);
 }
 
 int
@@ -205,7 +205,7 @@ r535_gr_oneinit(struct nvkm_gr *base)
 	{
 		NV_CHANNELGPFIFO_ALLOCATION_PARAMETERS *args;
 
-		args = nvkm_gsp_rm_alloc_get(&golden.vmm->rm.device.object, NVKM_RM_CHAN(0),
+		args = nvkm_gsp_rm_alloc_get(&gsp->internal.device.object, NVKM_RM_CHAN(0),
 					     device->fifo->func->chan.user.oclass,
 					     sizeof(*args), &golden.chan);
 		if (IS_ERR(args)) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
index 5e6cf57a6f70..195dd35393d9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c
@@ -179,6 +179,7 @@ r535_gsp_rpc_get_gsp_static_info(struct nvkm_gsp *gsp)
 	gsp->internal.client.object.parent = NULL;
 	gsp->internal.client.object.handle = rpc->hInternalClient;
 	gsp->internal.client.gsp = gsp;
+	INIT_LIST_HEAD(&gsp->internal.client.events);
 
 	gsp->internal.device.object.client = &gsp->internal.client;
 	gsp->internal.device.object.parent = &gsp->internal.client.object;
@@ -967,7 +968,11 @@ r535_gsp_msg_post_event(void *priv, u32 fn, void *repv, u32 repc)
 		   msg->status, msg->eventDataSize, msg->bNotifyList);
 
 	mutex_lock(&gsp->client_id.mutex);
-	client = idr_find(&gsp->client_id.idr, msg->hClient & 0xffff);
+	if (msg->hClient == gsp->internal.client.object.handle)
+		client = &gsp->internal.client;
+	else
+		client = idr_find(&gsp->client_id.idr, msg->hClient & 0xffff);
+
 	if (client) {
 		struct nvkm_gsp_event *event;
 		bool handled = false;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c
index 99af6c19a9a9..d1c5b00df459 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c
@@ -24,18 +24,15 @@
 #include "nvrm/vmm.h"
 
 static int
-r535_mmu_promote_vmm(struct nvkm_vmm *vmm)
+r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle)
 {
+	struct nvkm_mmu *mmu = vmm->mmu;
+	struct nvkm_gsp *gsp = mmu->subdev.device->gsp;
 	NV_VASPACE_ALLOCATION_PARAMETERS *args;
 	int ret;
 
-	ret = nvkm_gsp_client_device_ctor(vmm->mmu->subdev.device->gsp,
-					  &vmm->rm.client, &vmm->rm.device);
-	if (ret)
-		return ret;
-
-	args = nvkm_gsp_rm_alloc_get(&vmm->rm.device.object, NVKM_RM_VASPACE, FERMI_VASPACE_A,
-				     sizeof(*args), &vmm->rm.object);
+	args = nvkm_gsp_rm_alloc_get(&gsp->internal.device.object, handle,
+				     FERMI_VASPACE_A, sizeof(*args), &vmm->rm.object);
 	if (IS_ERR(args))
 		return PTR_ERR(args);
 
@@ -86,6 +83,25 @@ r535_mmu_promote_vmm(struct nvkm_vmm *vmm)
 	return ret;
 }
 
+static int
+r535_mmu_promote_vmm(struct nvkm_vmm *vmm)
+{
+	struct nvkm_mmu *mmu = vmm->mmu;
+	int id, ret;
+
+	id = ida_alloc_range(&mmu->rm.vmm_ids, 0, 0xffff + 1, GFP_KERNEL);
+	if (id < 0)
+		return id;
+
+	ret = r535_mmu_vaspace_new(vmm, NVKM_RM_VASPACE(id));
+	if (ret) {
+		ida_free(&mmu->rm.vmm_ids, id);
+		return ret;
+	}
+
+	return 0;
+}
+
 static void
 r535_mmu_dtor(struct nvkm_mmu *mmu)
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
index b67ace7ae93c..eb31c54b53ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
@@ -428,6 +428,7 @@ nvkm_mmu_ctor(const struct nvkm_mmu_func *func, struct nvkm_device *device,
 	mutex_init(&mmu->mutex);
 	mmu->user.ctor = nvkm_ummu_new;
 	mmu->user.base = func->mmu.user;
+	ida_init(&mmu->rm.vmm_ids);
 }
 
 int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
index 9c97800fe037..0768e5c1fad4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
@@ -1027,13 +1027,14 @@ nvkm_vmm_dump(struct nvkm_vmm *vmm)
 static void
 nvkm_vmm_dtor(struct nvkm_vmm *vmm)
 {
+	struct nvkm_mmu *mmu = vmm->mmu;
 	struct nvkm_vma *vma;
 	struct rb_node *node;
 
-	if (vmm->rm.client.gsp) {
+	if (vmm->rm.object.client) {
+		unsigned int id = vmm->rm.object.handle & 0xffff;
 		nvkm_gsp_rm_free(&vmm->rm.object);
-		nvkm_gsp_device_dtor(&vmm->rm.device);
-		nvkm_gsp_client_dtor(&vmm->rm.client);
+		ida_free(&mmu->rm.vmm_ids, id);
 		nvkm_vmm_put(vmm, &vmm->rm.rsvd);
 	}
 
-- 
2.49.0



More information about the Nouveau mailing list