notif.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2015-2021, Linaro Limited
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include <linux/arm-smccc.h>
  7. #include <linux/errno.h>
  8. #include <linux/slab.h>
  9. #include <linux/spinlock.h>
  10. #include <linux/tee_drv.h>
  11. #include "optee_private.h"
  12. struct notif_entry {
  13. struct list_head link;
  14. struct completion c;
  15. u_int key;
  16. };
  17. static bool have_key(struct optee *optee, u_int key)
  18. {
  19. struct notif_entry *entry;
  20. list_for_each_entry(entry, &optee->notif.db, link)
  21. if (entry->key == key)
  22. return true;
  23. return false;
  24. }
  25. int optee_notif_wait(struct optee *optee, u_int key)
  26. {
  27. unsigned long flags;
  28. struct notif_entry *entry;
  29. int rc = 0;
  30. if (key > optee->notif.max_key)
  31. return -EINVAL;
  32. entry = kmalloc(sizeof(*entry), GFP_KERNEL);
  33. if (!entry)
  34. return -ENOMEM;
  35. init_completion(&entry->c);
  36. entry->key = key;
  37. spin_lock_irqsave(&optee->notif.lock, flags);
  38. /*
  39. * If the bit is already set it means that the key has already
  40. * been posted and we must not wait.
  41. */
  42. if (test_bit(key, optee->notif.bitmap)) {
  43. clear_bit(key, optee->notif.bitmap);
  44. goto out;
  45. }
  46. /*
  47. * Check if someone is already waiting for this key. If there is
  48. * it's a programming error.
  49. */
  50. if (have_key(optee, key)) {
  51. rc = -EBUSY;
  52. goto out;
  53. }
  54. list_add_tail(&entry->link, &optee->notif.db);
  55. /*
  56. * Unlock temporarily and wait for completion.
  57. */
  58. spin_unlock_irqrestore(&optee->notif.lock, flags);
  59. wait_for_completion(&entry->c);
  60. spin_lock_irqsave(&optee->notif.lock, flags);
  61. list_del(&entry->link);
  62. out:
  63. spin_unlock_irqrestore(&optee->notif.lock, flags);
  64. kfree(entry);
  65. return rc;
  66. }
  67. int optee_notif_send(struct optee *optee, u_int key)
  68. {
  69. unsigned long flags;
  70. struct notif_entry *entry;
  71. if (key > optee->notif.max_key)
  72. return -EINVAL;
  73. spin_lock_irqsave(&optee->notif.lock, flags);
  74. list_for_each_entry(entry, &optee->notif.db, link)
  75. if (entry->key == key) {
  76. complete(&entry->c);
  77. goto out;
  78. }
  79. /* Only set the bit in case there where nobody waiting */
  80. set_bit(key, optee->notif.bitmap);
  81. out:
  82. spin_unlock_irqrestore(&optee->notif.lock, flags);
  83. return 0;
  84. }
  85. int optee_notif_init(struct optee *optee, u_int max_key)
  86. {
  87. spin_lock_init(&optee->notif.lock);
  88. INIT_LIST_HEAD(&optee->notif.db);
  89. optee->notif.bitmap = bitmap_zalloc(max_key, GFP_KERNEL);
  90. if (!optee->notif.bitmap)
  91. return -ENOMEM;
  92. optee->notif.max_key = max_key;
  93. return 0;
  94. }
  95. void optee_notif_uninit(struct optee *optee)
  96. {
  97. bitmap_free(optee->notif.bitmap);
  98. }