event.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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/notify.h>
  24. void
  25. nvkm_event_put(struct nvkm_event *event, u32 types, int index)
  26. {
  27. assert_spin_locked(&event->refs_lock);
  28. while (types) {
  29. int type = __ffs(types); types &= ~(1 << type);
  30. if (--event->refs[index * event->types_nr + type] == 0) {
  31. if (event->func->fini)
  32. event->func->fini(event, 1 << type, index);
  33. }
  34. }
  35. }
  36. void
  37. nvkm_event_get(struct nvkm_event *event, u32 types, int index)
  38. {
  39. assert_spin_locked(&event->refs_lock);
  40. while (types) {
  41. int type = __ffs(types); types &= ~(1 << type);
  42. if (++event->refs[index * event->types_nr + type] == 1) {
  43. if (event->func->init)
  44. event->func->init(event, 1 << type, index);
  45. }
  46. }
  47. }
  48. void
  49. nvkm_event_send(struct nvkm_event *event, u32 types, int index,
  50. void *data, u32 size)
  51. {
  52. struct nvkm_notify *notify;
  53. unsigned long flags;
  54. if (!event->refs || WARN_ON(index >= event->index_nr))
  55. return;
  56. spin_lock_irqsave(&event->list_lock, flags);
  57. list_for_each_entry(notify, &event->list, head) {
  58. if (notify->index == index && (notify->types & types)) {
  59. if (event->func->send) {
  60. event->func->send(data, size, notify);
  61. continue;
  62. }
  63. nvkm_notify_send(notify, data, size);
  64. }
  65. }
  66. spin_unlock_irqrestore(&event->list_lock, flags);
  67. }
  68. void
  69. nvkm_event_fini(struct nvkm_event *event)
  70. {
  71. if (event->refs) {
  72. kfree(event->refs);
  73. event->refs = NULL;
  74. }
  75. }
  76. int
  77. nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
  78. struct nvkm_event *event)
  79. {
  80. event->refs = kzalloc(array3_size(index_nr, types_nr,
  81. sizeof(*event->refs)),
  82. GFP_KERNEL);
  83. if (!event->refs)
  84. return -ENOMEM;
  85. event->func = func;
  86. event->types_nr = types_nr;
  87. event->index_nr = index_nr;
  88. spin_lock_init(&event->refs_lock);
  89. spin_lock_init(&event->list_lock);
  90. INIT_LIST_HEAD(&event->list);
  91. return 0;
  92. }