wilc_msgqueue.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "wilc_msgqueue.h"
  2. #include <linux/spinlock.h>
  3. #include "linux_wlan_common.h"
  4. #include <linux/errno.h>
  5. #include <linux/slab.h>
  6. /*!
  7. * @author syounan
  8. * @date 1 Sep 2010
  9. * @note copied from FLO glue implementatuion
  10. * @version 1.0
  11. */
  12. int wilc_mq_create(WILC_MsgQueueHandle *pHandle)
  13. {
  14. spin_lock_init(&pHandle->strCriticalSection);
  15. sema_init(&pHandle->hSem, 0);
  16. pHandle->pstrMessageList = NULL;
  17. pHandle->u32ReceiversCount = 0;
  18. pHandle->bExiting = false;
  19. return 0;
  20. }
  21. /*!
  22. * @author syounan
  23. * @date 1 Sep 2010
  24. * @note copied from FLO glue implementatuion
  25. * @version 1.0
  26. */
  27. int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle)
  28. {
  29. pHandle->bExiting = true;
  30. /* Release any waiting receiver thread. */
  31. while (pHandle->u32ReceiversCount > 0) {
  32. up(&pHandle->hSem);
  33. pHandle->u32ReceiversCount--;
  34. }
  35. while (pHandle->pstrMessageList) {
  36. Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
  37. kfree(pHandle->pstrMessageList);
  38. pHandle->pstrMessageList = pstrMessge;
  39. }
  40. return 0;
  41. }
  42. /*!
  43. * @author syounan
  44. * @date 1 Sep 2010
  45. * @note copied from FLO glue implementatuion
  46. * @version 1.0
  47. */
  48. int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
  49. const void *pvSendBuffer, u32 u32SendBufferSize)
  50. {
  51. unsigned long flags;
  52. Message *pstrMessage = NULL;
  53. if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) {
  54. PRINT_ER("pHandle or pvSendBuffer is null\n");
  55. return -EFAULT;
  56. }
  57. if (pHandle->bExiting) {
  58. PRINT_ER("pHandle fail\n");
  59. return -EFAULT;
  60. }
  61. /* construct a new message */
  62. pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
  63. if (!pstrMessage)
  64. return -ENOMEM;
  65. pstrMessage->u32Length = u32SendBufferSize;
  66. pstrMessage->pstrNext = NULL;
  67. pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize,
  68. GFP_ATOMIC);
  69. if (!pstrMessage->pvBuffer) {
  70. kfree(pstrMessage);
  71. return -ENOMEM;
  72. }
  73. spin_lock_irqsave(&pHandle->strCriticalSection, flags);
  74. /* add it to the message queue */
  75. if (!pHandle->pstrMessageList) {
  76. pHandle->pstrMessageList = pstrMessage;
  77. } else {
  78. Message *pstrTailMsg = pHandle->pstrMessageList;
  79. while (pstrTailMsg->pstrNext)
  80. pstrTailMsg = pstrTailMsg->pstrNext;
  81. pstrTailMsg->pstrNext = pstrMessage;
  82. }
  83. spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
  84. up(&pHandle->hSem);
  85. return 0;
  86. }
  87. /*!
  88. * @author syounan
  89. * @date 1 Sep 2010
  90. * @note copied from FLO glue implementatuion
  91. * @version 1.0
  92. */
  93. int wilc_mq_recv(WILC_MsgQueueHandle *pHandle,
  94. void *pvRecvBuffer, u32 u32RecvBufferSize,
  95. u32 *pu32ReceivedLength)
  96. {
  97. Message *pstrMessage;
  98. int result = 0;
  99. unsigned long flags;
  100. if ((!pHandle) || (u32RecvBufferSize == 0)
  101. || (!pvRecvBuffer) || (!pu32ReceivedLength)) {
  102. PRINT_ER("pHandle or pvRecvBuffer is null\n");
  103. return -EINVAL;
  104. }
  105. if (pHandle->bExiting) {
  106. PRINT_ER("pHandle fail\n");
  107. return -EFAULT;
  108. }
  109. spin_lock_irqsave(&pHandle->strCriticalSection, flags);
  110. pHandle->u32ReceiversCount++;
  111. spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
  112. down(&pHandle->hSem);
  113. /* other non-timeout scenarios */
  114. if (result) {
  115. PRINT_ER("Non-timeout\n");
  116. return result;
  117. }
  118. if (pHandle->bExiting) {
  119. PRINT_ER("pHandle fail\n");
  120. return -EFAULT;
  121. }
  122. spin_lock_irqsave(&pHandle->strCriticalSection, flags);
  123. pstrMessage = pHandle->pstrMessageList;
  124. if (!pstrMessage) {
  125. spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
  126. PRINT_ER("pstrMessage is null\n");
  127. return -EFAULT;
  128. }
  129. /* check buffer size */
  130. if (u32RecvBufferSize < pstrMessage->u32Length) {
  131. spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
  132. up(&pHandle->hSem);
  133. PRINT_ER("u32RecvBufferSize overflow\n");
  134. return -EOVERFLOW;
  135. }
  136. /* consume the message */
  137. pHandle->u32ReceiversCount--;
  138. memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
  139. *pu32ReceivedLength = pstrMessage->u32Length;
  140. pHandle->pstrMessageList = pstrMessage->pstrNext;
  141. kfree(pstrMessage->pvBuffer);
  142. kfree(pstrMessage);
  143. spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
  144. return result;
  145. }