File Index
Files and directories
Sign in
FILE

event.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/nouveau/nvkm/core/event.c C
  1/*
  2 * Copyright 2013-2014 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 <core/event.h>
 23#include <core/subdev.h>
 24
 25static void
 26nvkm_event_put(struct nvkm_event *event, u32 types, int index)
 27{
 28	assert_spin_locked(&event->refs_lock);
 29
 30	nvkm_trace(event->subdev, "event: decr %08x on %d\n", types, index);
 31
 32	while (types) {
 33		int type = __ffs(types); types &= ~(1 << type);
 34		if (--event->refs[index * event->types_nr + type] == 0) {
 35			nvkm_trace(event->subdev, "event: blocking %d on %d\n", type, index);
 36			if (event->func->fini)
 37				event->func->fini(event, 1 << type, index);
 38		}
 39	}
 40}
 41
 42static void
 43nvkm_event_get(struct nvkm_event *event, u32 types, int index)
 44{
 45	assert_spin_locked(&event->refs_lock);
 46
 47	nvkm_trace(event->subdev, "event: incr %08x on %d\n", types, index);
 48
 49	while (types) {
 50		int type = __ffs(types); types &= ~(1 << type);
 51		if (++event->refs[index * event->types_nr + type] == 1) {
 52			nvkm_trace(event->subdev, "event: allowing %d on %d\n", type, index);
 53			if (event->func->init)
 54				event->func->init(event, 1 << type, index);
 55		}
 56	}
 57}
 58
 59static void
 60nvkm_event_ntfy_state(struct nvkm_event_ntfy *ntfy)
 61{
 62	struct nvkm_event *event = ntfy->event;
 63	unsigned long flags;
 64
 65	nvkm_trace(event->subdev, "event: ntfy state changed\n");
 66	spin_lock_irqsave(&event->refs_lock, flags);
 67
 68	if (atomic_read(&ntfy->allowed) != ntfy->running) {
 69		if (ntfy->running) {
 70			nvkm_event_put(ntfy->event, ntfy->bits, ntfy->id);
 71			ntfy->running = false;
 72		} else {
 73			nvkm_event_get(ntfy->event, ntfy->bits, ntfy->id);
 74			ntfy->running = true;
 75		}
 76	}
 77
 78	spin_unlock_irqrestore(&event->refs_lock, flags);
 79}
 80
 81static void
 82nvkm_event_ntfy_remove(struct nvkm_event_ntfy *ntfy)
 83{
 84	write_lock_irq(&ntfy->event->list_lock);
 85	list_del_init(&ntfy->head);
 86	write_unlock_irq(&ntfy->event->list_lock);
 87}
 88
 89static void
 90nvkm_event_ntfy_insert(struct nvkm_event_ntfy *ntfy)
 91{
 92	write_lock_irq(&ntfy->event->list_lock);
 93	list_add_tail(&ntfy->head, &ntfy->event->ntfy);
 94	write_unlock_irq(&ntfy->event->list_lock);
 95}
 96
 97static void
 98nvkm_event_ntfy_block_(struct nvkm_event_ntfy *ntfy, bool wait)
 99{
100	struct nvkm_subdev *subdev = ntfy->event->subdev;
101
102	nvkm_trace(subdev, "event: ntfy block %08x on %d wait:%d\n", ntfy->bits, ntfy->id, wait);
103
104	if (atomic_xchg(&ntfy->allowed, 0) == 1) {
105		nvkm_event_ntfy_state(ntfy);
106		if (wait)
107			nvkm_event_ntfy_remove(ntfy);
108	}
109}
110
111void
112nvkm_event_ntfy_block(struct nvkm_event_ntfy *ntfy)
113{
114	if (ntfy->event)
115		nvkm_event_ntfy_block_(ntfy, ntfy->wait);
116}
117
118void
119nvkm_event_ntfy_allow(struct nvkm_event_ntfy *ntfy)
120{
121	nvkm_trace(ntfy->event->subdev, "event: ntfy allow %08x on %d\n", ntfy->bits, ntfy->id);
122
123	if (atomic_xchg(&ntfy->allowed, 1) == 0) {
124		nvkm_event_ntfy_state(ntfy);
125		if (ntfy->wait)
126			nvkm_event_ntfy_insert(ntfy);
127	}
128}
129
130void
131nvkm_event_ntfy_del(struct nvkm_event_ntfy *ntfy)
132{
133	struct nvkm_event *event = ntfy->event;
134
135	if (!event)
136		return;
137
138	nvkm_trace(event->subdev, "event: ntfy del %08x on %d\n", ntfy->bits, ntfy->id);
139
140	nvkm_event_ntfy_block_(ntfy, false);
141	nvkm_event_ntfy_remove(ntfy);
142	ntfy->event = NULL;
143}
144
145void
146nvkm_event_ntfy_add(struct nvkm_event *event, int id, u32 bits, bool wait, nvkm_event_func func,
147		    struct nvkm_event_ntfy *ntfy)
148{
149	nvkm_trace(event->subdev, "event: ntfy add %08x on %d wait:%d\n", id, bits, wait);
150
151	ntfy->event = event;
152	ntfy->id = id;
153	ntfy->bits = bits;
154	ntfy->wait = wait;
155	ntfy->func = func;
156	atomic_set(&ntfy->allowed, 0);
157	ntfy->running = false;
158	INIT_LIST_HEAD(&ntfy->head);
159	if (!ntfy->wait)
160		nvkm_event_ntfy_insert(ntfy);
161}
162
163bool
164nvkm_event_ntfy_valid(struct nvkm_event *event, int id, u32 bits)
165{
166	return true;
167}
168
169void
170nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits)
171{
172	struct nvkm_event_ntfy *ntfy, *ntmp;
173	unsigned long flags;
174
175	if (!event->refs || WARN_ON(id >= event->index_nr))
176		return;
177
178	nvkm_trace(event->subdev, "event: ntfy %08x on %d\n", bits, id);
179	read_lock_irqsave(&event->list_lock, flags);
180
181	list_for_each_entry_safe(ntfy, ntmp, &event->ntfy, head) {
182		if (ntfy->id == id && ntfy->bits & bits) {
183			if (atomic_read(&ntfy->allowed))
184				ntfy->func(ntfy, ntfy->bits & bits);
185		}
186	}
187
188	read_unlock_irqrestore(&event->list_lock, flags);
189}
190
191void
192nvkm_event_fini(struct nvkm_event *event)
193{
194	if (event->refs) {
195		kfree(event->refs);
196		event->refs = NULL;
197	}
198}
199
200int
201__nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
202		  int types_nr, int index_nr, struct nvkm_event *event)
203{
204	event->refs = kzalloc(array3_size(index_nr, types_nr, sizeof(*event->refs)), GFP_KERNEL);
205	if (!event->refs)
206		return -ENOMEM;
207
208	event->func = func;
209	event->subdev = subdev;
210	event->types_nr = types_nr;
211	event->index_nr = index_nr;
212	INIT_LIST_HEAD(&event->ntfy);
213	return 0;
214}
~/ Read-only file preview.