rsi_91x_ps.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /**
  2. * Copyright (c) 2014 Redpine Signals Inc.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/etherdevice.h>
  17. #include <linux/if.h>
  18. #include <linux/version.h>
  19. #include "rsi_debugfs.h"
  20. #include "rsi_mgmt.h"
  21. #include "rsi_common.h"
  22. #include "rsi_ps.h"
  23. char *str_psstate(enum ps_state state)
  24. {
  25. switch (state) {
  26. case PS_NONE:
  27. return "PS_NONE";
  28. case PS_DISABLE_REQ_SENT:
  29. return "PS_DISABLE_REQ_SENT";
  30. case PS_ENABLE_REQ_SENT:
  31. return "PS_ENABLE_REQ_SENT";
  32. case PS_ENABLED:
  33. return "PS_ENABLED";
  34. default:
  35. return "INVALID_STATE";
  36. }
  37. }
  38. static inline void rsi_modify_ps_state(struct rsi_hw *adapter,
  39. enum ps_state nstate)
  40. {
  41. rsi_dbg(INFO_ZONE, "PS state changed %s => %s\n",
  42. str_psstate(adapter->ps_state),
  43. str_psstate(nstate));
  44. adapter->ps_state = nstate;
  45. }
  46. void rsi_default_ps_params(struct rsi_hw *adapter)
  47. {
  48. struct rsi_ps_info *ps_info = &adapter->ps_info;
  49. ps_info->enabled = true;
  50. ps_info->sleep_type = RSI_SLEEP_TYPE_LP;
  51. ps_info->tx_threshold = 0;
  52. ps_info->rx_threshold = 0;
  53. ps_info->tx_hysterisis = 0;
  54. ps_info->rx_hysterisis = 0;
  55. ps_info->monitor_interval = 0;
  56. ps_info->listen_interval = RSI_DEF_LISTEN_INTERVAL;
  57. ps_info->num_bcns_per_lis_int = 0;
  58. ps_info->dtim_interval_duration = 0;
  59. ps_info->num_dtims_per_sleep = 0;
  60. ps_info->deep_sleep_wakeup_period = RSI_DEF_DS_WAKEUP_PERIOD;
  61. }
  62. void rsi_enable_ps(struct rsi_hw *adapter, struct ieee80211_vif *vif)
  63. {
  64. if (adapter->ps_state != PS_NONE) {
  65. rsi_dbg(ERR_ZONE,
  66. "%s: Cannot accept enable PS in %s state\n",
  67. __func__, str_psstate(adapter->ps_state));
  68. return;
  69. }
  70. if (rsi_send_ps_request(adapter, true, vif)) {
  71. rsi_dbg(ERR_ZONE,
  72. "%s: Failed to send PS request to device\n",
  73. __func__);
  74. return;
  75. }
  76. rsi_modify_ps_state(adapter, PS_ENABLE_REQ_SENT);
  77. }
  78. /* This function is used to disable power save */
  79. void rsi_disable_ps(struct rsi_hw *adapter, struct ieee80211_vif *vif)
  80. {
  81. if (adapter->ps_state != PS_ENABLED) {
  82. rsi_dbg(ERR_ZONE,
  83. "%s: Cannot accept disable PS in %s state\n",
  84. __func__, str_psstate(adapter->ps_state));
  85. return;
  86. }
  87. if (rsi_send_ps_request(adapter, false, vif)) {
  88. rsi_dbg(ERR_ZONE,
  89. "%s: Failed to send PS request to device\n",
  90. __func__);
  91. return;
  92. }
  93. rsi_modify_ps_state(adapter, PS_DISABLE_REQ_SENT);
  94. }
  95. void rsi_conf_uapsd(struct rsi_hw *adapter, struct ieee80211_vif *vif)
  96. {
  97. int ret;
  98. if (adapter->ps_state != PS_ENABLED)
  99. return;
  100. ret = rsi_send_ps_request(adapter, false, vif);
  101. if (!ret)
  102. ret = rsi_send_ps_request(adapter, true, vif);
  103. if (ret)
  104. rsi_dbg(ERR_ZONE,
  105. "%s: Failed to send PS request to device\n",
  106. __func__);
  107. }
  108. int rsi_handle_ps_confirm(struct rsi_hw *adapter, u8 *msg)
  109. {
  110. u16 cfm_type = get_unaligned_le16(msg + PS_CONFIRM_INDEX);
  111. switch (cfm_type) {
  112. case RSI_SLEEP_REQUEST:
  113. if (adapter->ps_state == PS_ENABLE_REQ_SENT)
  114. rsi_modify_ps_state(adapter, PS_ENABLED);
  115. break;
  116. case RSI_WAKEUP_REQUEST:
  117. if (adapter->ps_state == PS_DISABLE_REQ_SENT)
  118. rsi_modify_ps_state(adapter, PS_NONE);
  119. break;
  120. default:
  121. rsi_dbg(ERR_ZONE,
  122. "Invalid PS confirm type %x in state %s\n",
  123. cfm_type, str_psstate(adapter->ps_state));
  124. return -1;
  125. }
  126. return 0;
  127. }