aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rsi/rsi_91x_mgmt.c
diff options
context:
space:
mode:
authorPrameela Rani Garnepudi <prameela.j04cs@gmail.com>2018-12-27 14:56:18 +0530
committerKalle Valo <kvalo@codeaurora.org>2019-01-10 13:38:26 +0200
commit7fdcb8e1266093eb2ff1bc3ab430daf4775388ad (patch)
tree1402d5f2de08927e472570607cc6a2ff4f67b2a1 /drivers/net/wireless/rsi/rsi_91x_mgmt.c
parentbrcmfmac: add a check for the status of usb_register (diff)
downloadlinux-dev-7fdcb8e1266093eb2ff1bc3ab430daf4775388ad.tar.xz
linux-dev-7fdcb8e1266093eb2ff1bc3ab430daf4775388ad.zip
rsi: add support for hardware scan offload
With the current approach of scanning, roaming delays are observed. Firmware has support for back ground scanning. To get this advantage, mac80211 hardware scan is implemented, which decides type of scan to do based on connected state. When station is in not connected, driver returns with special value 1 to trigger software scan in mac80211. In case of connected state, background scan will be triggered. Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com> Signed-off-by: Siva Rebbagondla <siva.rebbagondla@redpinesignals.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/rsi/rsi_91x_mgmt.c')
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 1095df7d9573..404241424a62 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -15,6 +15,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/timer.h>
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_ps.h"
@@ -236,6 +237,18 @@ static void rsi_set_default_parameters(struct rsi_common *common)
common->dtim_cnt = RSI_DTIM_COUNT;
}
+void init_bgscan_params(struct rsi_common *common)
+{
+ memset((u8 *)&common->bgscan, 0, sizeof(struct rsi_bgscan_params));
+ common->bgscan.bgscan_threshold = RSI_DEF_BGSCAN_THRLD;
+ common->bgscan.roam_threshold = RSI_DEF_ROAM_THRLD;
+ common->bgscan.bgscan_periodicity = RSI_BGSCAN_PERIODICITY;
+ common->bgscan.num_bgscan_channels = 0;
+ common->bgscan.two_probe = 1;
+ common->bgscan.active_scan_duration = RSI_ACTIVE_SCAN_TIME;
+ common->bgscan.passive_scan_duration = RSI_PASSIVE_SCAN_TIME;
+}
+
/**
* rsi_set_contention_vals() - This function sets the contention values for the
* backoff procedure.
@@ -1628,6 +1641,107 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
}
#endif
+int rsi_send_bgscan_params(struct rsi_common *common, int enable)
+{
+ struct rsi_bgscan_params *params = &common->bgscan;
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct rsi_bgscan_config *bgscan;
+ struct sk_buff *skb;
+ u16 frame_len = sizeof(*bgscan);
+ u8 i;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len);
+
+ bgscan = (struct rsi_bgscan_config *)skb->data;
+ rsi_set_len_qno(&bgscan->desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q);
+ bgscan->desc_dword0.frame_type = BG_SCAN_PARAMS;
+ bgscan->bgscan_threshold = cpu_to_le16(params->bgscan_threshold);
+ bgscan->roam_threshold = cpu_to_le16(params->roam_threshold);
+ if (enable)
+ bgscan->bgscan_periodicity =
+ cpu_to_le16(params->bgscan_periodicity);
+ bgscan->active_scan_duration =
+ cpu_to_le16(params->active_scan_duration);
+ bgscan->passive_scan_duration =
+ cpu_to_le16(params->passive_scan_duration);
+ bgscan->two_probe = params->two_probe;
+
+ bgscan->num_bgscan_channels = scan_req->n_channels;
+ for (i = 0; i < bgscan->num_bgscan_channels; i++)
+ bgscan->channels2scan[i] =
+ cpu_to_le16(scan_req->channels[i]->hw_value);
+
+ skb_put(skb, frame_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/* This function sends the probe request to be used by firmware in
+ * background scan
+ */
+int rsi_send_bgscan_probe_req(struct rsi_common *common,
+ struct ieee80211_vif *vif)
+{
+ struct cfg80211_scan_request *scan_req = common->hwscan;
+ struct rsi_bgscan_probe *bgscan;
+ struct sk_buff *skb;
+ struct sk_buff *probereq_skb;
+ u16 frame_len = sizeof(*bgscan);
+ size_t ssid_len = 0;
+ u8 *ssid = NULL;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending bgscan probe req frame\n", __func__);
+
+ if (common->priv->sc_nvifs <= 0)
+ return -ENODEV;
+
+ if (scan_req->n_ssids) {
+ ssid = scan_req->ssids[0].ssid;
+ ssid_len = scan_req->ssids[0].ssid_len;
+ }
+
+ skb = dev_alloc_skb(frame_len + MAX_BGSCAN_PROBE_REQ_LEN);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len + MAX_BGSCAN_PROBE_REQ_LEN);
+
+ bgscan = (struct rsi_bgscan_probe *)skb->data;
+ bgscan->desc_dword0.frame_type = BG_SCAN_PROBE_REQ;
+ bgscan->flags = cpu_to_le16(HOST_BG_SCAN_TRIG);
+ if (common->band == NL80211_BAND_5GHZ) {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_6);
+ bgscan->def_chan = cpu_to_le16(40);
+ } else {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_1);
+ bgscan->def_chan = cpu_to_le16(11);
+ }
+ bgscan->channel_scan_time = cpu_to_le16(RSI_CHANNEL_SCAN_TIME);
+
+ probereq_skb = ieee80211_probereq_get(common->priv->hw, vif->addr, ssid,
+ ssid_len, scan_req->ie_len);
+
+ memcpy(&skb->data[frame_len], probereq_skb->data, probereq_skb->len);
+
+ bgscan->probe_req_length = cpu_to_le16(probereq_skb->len);
+
+ rsi_set_len_qno(&bgscan->desc_dword0.len_qno,
+ (frame_len - FRAME_DESC_SZ + probereq_skb->len),
+ RSI_WIFI_MGMT_Q);
+
+ skb_put(skb, frame_len + probereq_skb->len);
+
+ dev_kfree_skb(probereq_skb);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
@@ -1771,9 +1885,28 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
return 0;
}
break;
+
+ case SCAN_REQUEST:
+ rsi_dbg(INFO_ZONE, "Set channel confirm\n");
+ break;
+
case WAKEUP_SLEEP_REQUEST:
rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
return rsi_handle_ps_confirm(adapter, msg);
+
+ case BG_SCAN_PROBE_REQ:
+ rsi_dbg(INFO_ZONE, "BG scan complete event\n");
+ if (common->bgscan_en) {
+ struct cfg80211_scan_info info;
+
+ if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN))
+ common->bgscan_en = 0;
+ info.aborted = false;
+ ieee80211_scan_completed(adapter->hw, &info);
+ }
+ rsi_dbg(INFO_ZONE, "Background scan completed\n");
+ break;
+
default:
rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n",
__func__);