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