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