rmnet_module.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include "rmnet_module.h"
  13. struct rmnet_module_hook_info {
  14. void *func __rcu;
  15. };
  16. static struct rmnet_module_hook_info
  17. rmnet_module_hooks[__RMNET_MODULE_NUM_HOOKS];
  18. void
  19. rmnet_module_hook_register(const struct rmnet_module_hook_register_info *info,
  20. int hook_count)
  21. {
  22. struct rmnet_module_hook_info *hook_info;
  23. int i;
  24. for (i = 0; i < hook_count; i++) {
  25. int hook = info[i].hooknum;
  26. if (hook < __RMNET_MODULE_NUM_HOOKS) {
  27. hook_info = &rmnet_module_hooks[hook];
  28. rcu_assign_pointer(hook_info->func, info[i].func);
  29. }
  30. }
  31. }
  32. EXPORT_SYMBOL(rmnet_module_hook_register);
  33. bool rmnet_module_hook_is_set(int hook)
  34. {
  35. if (hook >= __RMNET_MODULE_NUM_HOOKS)
  36. return false;
  37. return rcu_dereference(rmnet_module_hooks[hook].func) != NULL;
  38. }
  39. EXPORT_SYMBOL(rmnet_module_hook_is_set);
  40. void
  41. rmnet_module_hook_unregister_no_sync(const struct rmnet_module_hook_register_info *info,
  42. int hook_count)
  43. {
  44. struct rmnet_module_hook_info *hook_info;
  45. int i;
  46. for (i = 0; i < hook_count; i++) {
  47. int hook = info[i].hooknum;
  48. if (hook < __RMNET_MODULE_NUM_HOOKS) {
  49. hook_info = &rmnet_module_hooks[hook];
  50. rcu_assign_pointer(hook_info->func, NULL);
  51. }
  52. }
  53. }
  54. EXPORT_SYMBOL(rmnet_module_hook_unregister_no_sync);
  55. #define __RMNET_HOOK_DEFINE(call, hook_num, proto, args, ret_type) \
  56. int rmnet_module_hook_##call( \
  57. __RMNET_HOOK_PROTO(RMNET_HOOK_PARAMS(proto), ret_type) \
  58. ) \
  59. { \
  60. ret_type (*__func)(proto); \
  61. struct rmnet_module_hook_info *__info = \
  62. &rmnet_module_hooks[hook_num]; \
  63. int __ret = 0; \
  64. \
  65. rcu_read_lock(); \
  66. __func = rcu_dereference(__info->func); \
  67. if (__func) { \
  68. RMNET_HOOK_IF_NON_VOID_TYPE(ret_type)( ret_type __rc = ) \
  69. __func(args); \
  70. __ret = 1; \
  71. \
  72. RMNET_HOOK_IF_NON_VOID_TYPE(ret_type)( if (__ret_code) \
  73. *__ret_code = __rc; )\
  74. } \
  75. \
  76. rcu_read_unlock(); \
  77. return __ret; \
  78. } \
  79. EXPORT_SYMBOL(rmnet_module_hook_##call);
  80. #undef RMNET_MODULE_HOOK
  81. #define RMNET_MODULE_HOOK(call, hook_num, proto, args, ret_type) \
  82. __RMNET_HOOK_DEFINE(call, hook_num, RMNET_HOOK_PARAMS(proto), \
  83. RMNET_HOOK_PARAMS(args), ret_type)
  84. #define __RMNET_HOOK_MULTIREAD__
  85. #include "rmnet_hook.h"