event.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * This file is part of wl1251
  4. *
  5. * Copyright (c) 1998-2007 Texas Instruments Incorporated
  6. * Copyright (C) 2008 Nokia Corporation
  7. */
  8. #include "wl1251.h"
  9. #include "reg.h"
  10. #include "io.h"
  11. #include "event.h"
  12. #include "ps.h"
  13. static int wl1251_event_scan_complete(struct wl1251 *wl,
  14. struct event_mailbox *mbox)
  15. {
  16. int ret = 0;
  17. wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
  18. mbox->scheduled_scan_status,
  19. mbox->scheduled_scan_channels);
  20. if (wl->scanning) {
  21. struct cfg80211_scan_info info = {
  22. .aborted = false,
  23. };
  24. ieee80211_scan_completed(wl->hw, &info);
  25. wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
  26. wl->scanning = false;
  27. if (wl->hw->conf.flags & IEEE80211_CONF_IDLE)
  28. ret = wl1251_ps_set_mode(wl, STATION_IDLE);
  29. }
  30. return ret;
  31. }
  32. #define WL1251_PSM_ENTRY_RETRIES 3
  33. static int wl1251_event_ps_report(struct wl1251 *wl,
  34. struct event_mailbox *mbox)
  35. {
  36. int ret = 0;
  37. wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
  38. switch (mbox->ps_status) {
  39. case EVENT_ENTER_POWER_SAVE_FAIL:
  40. wl1251_debug(DEBUG_PSM, "PSM entry failed");
  41. if (wl->station_mode != STATION_POWER_SAVE_MODE) {
  42. /* remain in active mode */
  43. wl->psm_entry_retry = 0;
  44. break;
  45. }
  46. if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) {
  47. wl->psm_entry_retry++;
  48. ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
  49. } else {
  50. wl1251_error("Power save entry failed, giving up");
  51. wl->psm_entry_retry = 0;
  52. }
  53. break;
  54. case EVENT_ENTER_POWER_SAVE_SUCCESS:
  55. case EVENT_EXIT_POWER_SAVE_FAIL:
  56. case EVENT_EXIT_POWER_SAVE_SUCCESS:
  57. default:
  58. wl->psm_entry_retry = 0;
  59. break;
  60. }
  61. return ret;
  62. }
  63. static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
  64. {
  65. wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
  66. wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
  67. wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
  68. }
  69. static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
  70. {
  71. int ret;
  72. u32 vector;
  73. wl1251_event_mbox_dump(mbox);
  74. vector = mbox->events_vector & ~(mbox->events_mask);
  75. wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
  76. if (vector & SCAN_COMPLETE_EVENT_ID) {
  77. ret = wl1251_event_scan_complete(wl, mbox);
  78. if (ret < 0)
  79. return ret;
  80. }
  81. if (vector & BSS_LOSE_EVENT_ID) {
  82. wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
  83. if (wl->psm_requested &&
  84. wl->station_mode != STATION_ACTIVE_MODE) {
  85. ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
  86. if (ret < 0)
  87. return ret;
  88. }
  89. }
  90. if (vector & PS_REPORT_EVENT_ID) {
  91. wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
  92. ret = wl1251_event_ps_report(wl, mbox);
  93. if (ret < 0)
  94. return ret;
  95. }
  96. if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
  97. wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
  98. /* indicate to the stack, that beacons have been lost */
  99. if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION)
  100. ieee80211_beacon_loss(wl->vif);
  101. }
  102. if (vector & REGAINED_BSS_EVENT_ID) {
  103. if (wl->psm_requested) {
  104. ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
  105. if (ret < 0)
  106. return ret;
  107. }
  108. }
  109. if (wl->vif && wl->rssi_thold) {
  110. if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) {
  111. wl1251_debug(DEBUG_EVENT,
  112. "ROAMING_TRIGGER_LOW_RSSI_EVENT");
  113. ieee80211_cqm_rssi_notify(wl->vif,
  114. NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
  115. 0, GFP_KERNEL);
  116. }
  117. if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
  118. wl1251_debug(DEBUG_EVENT,
  119. "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
  120. ieee80211_cqm_rssi_notify(wl->vif,
  121. NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
  122. 0, GFP_KERNEL);
  123. }
  124. }
  125. return 0;
  126. }
  127. /*
  128. * Poll the mailbox event field until any of the bits in the mask is set or a
  129. * timeout occurs (WL1251_EVENT_TIMEOUT in msecs)
  130. */
  131. int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms)
  132. {
  133. u32 events_vector, event;
  134. unsigned long timeout;
  135. timeout = jiffies + msecs_to_jiffies(timeout_ms);
  136. do {
  137. if (time_after(jiffies, timeout))
  138. return -ETIMEDOUT;
  139. msleep(1);
  140. /* read from both event fields */
  141. events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[0]);
  142. event = events_vector & mask;
  143. events_vector = wl1251_mem_read32(wl, wl->mbox_ptr[1]);
  144. event |= events_vector & mask;
  145. } while (!event);
  146. return 0;
  147. }
  148. int wl1251_event_unmask(struct wl1251 *wl)
  149. {
  150. int ret;
  151. ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask));
  152. if (ret < 0)
  153. return ret;
  154. return 0;
  155. }
  156. void wl1251_event_mbox_config(struct wl1251 *wl)
  157. {
  158. wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
  159. wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
  160. wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
  161. wl->mbox_ptr[0], wl->mbox_ptr[1]);
  162. }
  163. int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
  164. {
  165. struct event_mailbox *mbox;
  166. int ret;
  167. wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
  168. if (mbox_num > 1)
  169. return -EINVAL;
  170. mbox = kmalloc(sizeof(*mbox), GFP_KERNEL);
  171. if (!mbox) {
  172. wl1251_error("can not allocate mbox buffer");
  173. return -ENOMEM;
  174. }
  175. /* first we read the mbox descriptor */
  176. wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], mbox,
  177. sizeof(*mbox));
  178. /* process the descriptor */
  179. ret = wl1251_event_process(wl, mbox);
  180. kfree(mbox);
  181. if (ret < 0)
  182. return ret;
  183. /* then we let the firmware know it can go on...*/
  184. wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
  185. return 0;
  186. }