Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2014 Redpine Signals Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include <linux/etherdevice.h>
0018 #include <linux/if.h>
0019 #include "rsi_debugfs.h"
0020 #include "rsi_mgmt.h"
0021 #include "rsi_common.h"
0022 #include "rsi_ps.h"
0023 
0024 char *str_psstate(enum ps_state state)
0025 {
0026     switch (state) {
0027     case PS_NONE:
0028         return "PS_NONE";
0029     case PS_DISABLE_REQ_SENT:
0030         return "PS_DISABLE_REQ_SENT";
0031     case PS_ENABLE_REQ_SENT:
0032         return "PS_ENABLE_REQ_SENT";
0033     case PS_ENABLED:
0034         return "PS_ENABLED";
0035     default:
0036         return "INVALID_STATE";
0037     }
0038 }
0039 
0040 static inline void rsi_modify_ps_state(struct rsi_hw *adapter,
0041                        enum ps_state nstate)
0042 {
0043     rsi_dbg(INFO_ZONE, "PS state changed %s => %s\n",
0044         str_psstate(adapter->ps_state),
0045         str_psstate(nstate));
0046 
0047     adapter->ps_state = nstate;
0048 }
0049 
0050 void rsi_default_ps_params(struct rsi_hw *adapter)
0051 {
0052     struct rsi_ps_info *ps_info = &adapter->ps_info;
0053 
0054     ps_info->enabled = true;
0055     ps_info->sleep_type = RSI_SLEEP_TYPE_LP;
0056     ps_info->tx_threshold = 0;
0057     ps_info->rx_threshold = 0;
0058     ps_info->tx_hysterisis = 0;
0059     ps_info->rx_hysterisis = 0;
0060     ps_info->monitor_interval = 0;
0061     ps_info->listen_interval = RSI_DEF_LISTEN_INTERVAL;
0062     ps_info->num_bcns_per_lis_int = 0;
0063     ps_info->dtim_interval_duration = 0;
0064     ps_info->num_dtims_per_sleep = 0;
0065     ps_info->deep_sleep_wakeup_period = RSI_DEF_DS_WAKEUP_PERIOD;
0066 }
0067 
0068 void rsi_enable_ps(struct rsi_hw *adapter, struct ieee80211_vif *vif)
0069 {
0070     if (adapter->ps_state != PS_NONE) {
0071         rsi_dbg(ERR_ZONE,
0072             "%s: Cannot accept enable PS in %s state\n",
0073             __func__, str_psstate(adapter->ps_state));
0074         return;
0075     }
0076 
0077     if (rsi_send_ps_request(adapter, true, vif)) {
0078         rsi_dbg(ERR_ZONE,
0079             "%s: Failed to send PS request to device\n",
0080             __func__);
0081         return;
0082     }
0083 
0084     rsi_modify_ps_state(adapter, PS_ENABLE_REQ_SENT);
0085 }
0086 
0087 /* This function is used to disable power save */
0088 void rsi_disable_ps(struct rsi_hw *adapter, struct ieee80211_vif *vif)
0089 {
0090     if (adapter->ps_state != PS_ENABLED) {
0091         rsi_dbg(ERR_ZONE,
0092             "%s: Cannot accept disable PS in %s state\n",
0093             __func__, str_psstate(adapter->ps_state));
0094         return;
0095     }
0096 
0097     if (rsi_send_ps_request(adapter, false, vif)) {
0098         rsi_dbg(ERR_ZONE,
0099             "%s: Failed to send PS request to device\n",
0100             __func__);
0101         return;
0102     }
0103 
0104     rsi_modify_ps_state(adapter, PS_DISABLE_REQ_SENT);
0105 }
0106 
0107 void rsi_conf_uapsd(struct rsi_hw *adapter, struct ieee80211_vif *vif)
0108 {
0109     int ret;
0110 
0111     if (adapter->ps_state != PS_ENABLED)
0112         return;
0113 
0114     ret = rsi_send_ps_request(adapter, false, vif);
0115     if (!ret)
0116         ret = rsi_send_ps_request(adapter, true, vif);
0117     if (ret)
0118         rsi_dbg(ERR_ZONE,
0119             "%s: Failed to send PS request to device\n",
0120             __func__);
0121 }
0122 
0123 int rsi_handle_ps_confirm(struct rsi_hw *adapter, u8 *msg)
0124 {
0125     u16 cfm_type = get_unaligned_le16(msg + PS_CONFIRM_INDEX);
0126 
0127     switch (cfm_type) {
0128     case RSI_SLEEP_REQUEST:
0129         if (adapter->ps_state == PS_ENABLE_REQ_SENT)
0130             rsi_modify_ps_state(adapter, PS_ENABLED);
0131         break;
0132     case RSI_WAKEUP_REQUEST:
0133         if (adapter->ps_state == PS_DISABLE_REQ_SENT)
0134             rsi_modify_ps_state(adapter, PS_NONE);
0135         break;
0136     default:
0137         rsi_dbg(ERR_ZONE,
0138             "Invalid PS confirm type %x in state %s\n",
0139             cfm_type, str_psstate(adapter->ps_state));
0140         return -1;
0141     }
0142 
0143     return 0;
0144 }
0145