xref: /linux/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/device.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 /*
2  * Copyright 2023 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 #include <rm/rm.h>
23 
24 #include "nvrm/device.h"
25 #include "nvrm/event.h"
26 
27 static void
r535_gsp_event_dtor(struct nvkm_gsp_event * event)28 r535_gsp_event_dtor(struct nvkm_gsp_event *event)
29 {
30 	struct nvkm_gsp_device *device = event->device;
31 	struct nvkm_gsp_client *client = device->object.client;
32 	struct nvkm_gsp *gsp = client->gsp;
33 
34 	mutex_lock(&gsp->client_id.mutex);
35 	if (event->func) {
36 		list_del(&event->head);
37 		event->func = NULL;
38 	}
39 	mutex_unlock(&gsp->client_id.mutex);
40 
41 	nvkm_gsp_rm_free(&event->object);
42 	event->device = NULL;
43 }
44 
45 static int
r535_gsp_device_event_get(struct nvkm_gsp_event * event)46 r535_gsp_device_event_get(struct nvkm_gsp_event *event)
47 {
48 	struct nvkm_gsp_device *device = event->device;
49 	NV2080_CTRL_EVENT_SET_NOTIFICATION_PARAMS *ctrl;
50 
51 	ctrl = nvkm_gsp_rm_ctrl_get(&device->subdevice,
52 				    NV2080_CTRL_CMD_EVENT_SET_NOTIFICATION, sizeof(*ctrl));
53 	if (IS_ERR(ctrl))
54 		return PTR_ERR(ctrl);
55 
56 	ctrl->event = event->id;
57 	ctrl->action = NV2080_CTRL_EVENT_SET_NOTIFICATION_ACTION_REPEAT;
58 	return nvkm_gsp_rm_ctrl_wr(&device->subdevice, ctrl);
59 }
60 
61 static int
r535_gsp_device_event_ctor(struct nvkm_gsp_device * device,u32 handle,u32 id,nvkm_gsp_event_func func,struct nvkm_gsp_event * event)62 r535_gsp_device_event_ctor(struct nvkm_gsp_device *device, u32 handle, u32 id,
63 			   nvkm_gsp_event_func func, struct nvkm_gsp_event *event)
64 {
65 	struct nvkm_gsp_client *client = device->object.client;
66 	struct nvkm_gsp *gsp = client->gsp;
67 	NV0005_ALLOC_PARAMETERS *args;
68 	int ret;
69 
70 	args = nvkm_gsp_rm_alloc_get(&device->subdevice, handle,
71 				     NV01_EVENT_KERNEL_CALLBACK_EX, sizeof(*args),
72 				     &event->object);
73 	if (IS_ERR(args))
74 		return PTR_ERR(args);
75 
76 	args->hParentClient = client->object.handle;
77 	args->hSrcResource = 0;
78 	args->hClass = NV01_EVENT_KERNEL_CALLBACK_EX;
79 	args->notifyIndex = NV01_EVENT_CLIENT_RM | id;
80 	args->data = NULL;
81 
82 	ret = nvkm_gsp_rm_alloc_wr(&event->object, args);
83 	if (ret)
84 		return ret;
85 
86 	event->device = device;
87 	event->id = id;
88 
89 	ret = r535_gsp_device_event_get(event);
90 	if (ret) {
91 		nvkm_gsp_event_dtor(event);
92 		return ret;
93 	}
94 
95 	mutex_lock(&gsp->client_id.mutex);
96 	event->func = func;
97 	list_add(&event->head, &client->events);
98 	mutex_unlock(&gsp->client_id.mutex);
99 	return 0;
100 }
101 
102 static void
r535_gsp_device_dtor(struct nvkm_gsp_device * device)103 r535_gsp_device_dtor(struct nvkm_gsp_device *device)
104 {
105 	nvkm_gsp_rm_free(&device->subdevice);
106 	nvkm_gsp_rm_free(&device->object);
107 }
108 
109 static int
r535_gsp_subdevice_ctor(struct nvkm_gsp_device * device)110 r535_gsp_subdevice_ctor(struct nvkm_gsp_device *device)
111 {
112 	NV2080_ALLOC_PARAMETERS *args;
113 
114 	return nvkm_gsp_rm_alloc(&device->object, NVKM_RM_SUBDEVICE, NV20_SUBDEVICE_0,
115 				 sizeof(*args), &device->subdevice);
116 }
117 
118 static int
r535_gsp_device_ctor(struct nvkm_gsp_client * client,struct nvkm_gsp_device * device)119 r535_gsp_device_ctor(struct nvkm_gsp_client *client, struct nvkm_gsp_device *device)
120 {
121 	NV0080_ALLOC_PARAMETERS *args;
122 	int ret;
123 
124 	args = nvkm_gsp_rm_alloc_get(&client->object, NVKM_RM_DEVICE, NV01_DEVICE_0, sizeof(*args),
125 				     &device->object);
126 	if (IS_ERR(args))
127 		return PTR_ERR(args);
128 
129 	args->hClientShare = client->object.handle;
130 
131 	ret = nvkm_gsp_rm_alloc_wr(&device->object, args);
132 	if (ret)
133 		return ret;
134 
135 	ret = r535_gsp_subdevice_ctor(device);
136 	if (ret)
137 		nvkm_gsp_rm_free(&device->object);
138 
139 	return ret;
140 }
141 
142 const struct nvkm_rm_api_device
143 r535_device = {
144 	.ctor = r535_gsp_device_ctor,
145 	.dtor = r535_gsp_device_dtor,
146 	.event.ctor = r535_gsp_device_event_ctor,
147 	.event.dtor = r535_gsp_event_dtor,
148 };
149