0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include <core/event.h>
0023 #include <core/notify.h>
0024
0025 void
0026 nvkm_event_put(struct nvkm_event *event, u32 types, int index)
0027 {
0028 assert_spin_locked(&event->refs_lock);
0029 while (types) {
0030 int type = __ffs(types); types &= ~(1 << type);
0031 if (--event->refs[index * event->types_nr + type] == 0) {
0032 if (event->func->fini)
0033 event->func->fini(event, 1 << type, index);
0034 }
0035 }
0036 }
0037
0038 void
0039 nvkm_event_get(struct nvkm_event *event, u32 types, int index)
0040 {
0041 assert_spin_locked(&event->refs_lock);
0042 while (types) {
0043 int type = __ffs(types); types &= ~(1 << type);
0044 if (++event->refs[index * event->types_nr + type] == 1) {
0045 if (event->func->init)
0046 event->func->init(event, 1 << type, index);
0047 }
0048 }
0049 }
0050
0051 void
0052 nvkm_event_send(struct nvkm_event *event, u32 types, int index,
0053 void *data, u32 size)
0054 {
0055 struct nvkm_notify *notify;
0056 unsigned long flags;
0057
0058 if (!event->refs || WARN_ON(index >= event->index_nr))
0059 return;
0060
0061 spin_lock_irqsave(&event->list_lock, flags);
0062 list_for_each_entry(notify, &event->list, head) {
0063 if (notify->index == index && (notify->types & types)) {
0064 if (event->func->send) {
0065 event->func->send(data, size, notify);
0066 continue;
0067 }
0068 nvkm_notify_send(notify, data, size);
0069 }
0070 }
0071 spin_unlock_irqrestore(&event->list_lock, flags);
0072 }
0073
0074 void
0075 nvkm_event_fini(struct nvkm_event *event)
0076 {
0077 if (event->refs) {
0078 kfree(event->refs);
0079 event->refs = NULL;
0080 }
0081 }
0082
0083 int
0084 nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
0085 struct nvkm_event *event)
0086 {
0087 event->refs = kzalloc(array3_size(index_nr, types_nr,
0088 sizeof(*event->refs)),
0089 GFP_KERNEL);
0090 if (!event->refs)
0091 return -ENOMEM;
0092
0093 event->func = func;
0094 event->types_nr = types_nr;
0095 event->index_nr = index_nr;
0096 spin_lock_init(&event->refs_lock);
0097 spin_lock_init(&event->list_lock);
0098 INIT_LIST_HEAD(&event->list);
0099 return 0;
0100 }