blob: ef54c99b1f899d797d09078a4951d17df579d205 [file] [log] [blame]
Qiwei Caie689a262018-07-26 15:50:22 +08001/*
2 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: wlan_hdd_ota_test.c
21 *
22 * WLAN OTA test functions
23 *
24 */
25
26#include <wlan_hdd_includes.h>
27#include <linux/netdevice.h>
28#include <linux/skbuff.h>
29#include <linux/etherdevice.h>
30#include <linux/if_ether.h>
31#include <sme_power_save_api.h>
32#include <wlan_hdd_ota_test.h>
33
34static const struct
35nla_policy
36qca_wlan_vendor_ota_test_policy
37[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
38 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
39};
40
41/**
42 * __wlan_hdd_cfg80211_set_ota_test() - enable/disable OTA test
43 * @wiphy: Pointer to wireless phy
44 * @wdev: Pointer to wireless device
45 * @data: Pointer to data
46 * @data_len: Data length
47 *
48 * Return: 0 on success, negative errno on failure
49 */
50static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
51 struct wireless_dev *wdev,
52 const void *data,
53 int data_len)
54{
55 struct net_device *dev = wdev->netdev;
56 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
57 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
58 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
59 uint8_t ota_enable = 0;
60 QDF_STATUS status;
61 uint32_t current_roam_state;
62 mac_handle_t mac_handle;
63
64 hdd_enter_dev(dev);
65
66 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
67 hdd_err("Command not allowed in FTM mode");
68 return -EPERM;
69 }
70
71 if (wlan_hdd_validate_context(hdd_ctx) != 0)
72 return -EINVAL;
73
74 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
75 data, data_len,
76 qca_wlan_vendor_ota_test_policy)) {
77 hdd_err("invalid attr");
78 return -EINVAL;
79 }
80
81 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
82 hdd_err("attr ota test failed");
83 return -EINVAL;
84 }
85
86 ota_enable = nla_get_u8(
87 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
88
89 hdd_debug(" OTA test enable = %d", ota_enable);
90 if (ota_enable != 1) {
91 hdd_err("Invalid value, only enable test mode is supported!");
92 return -EINVAL;
93 }
94
95 mac_handle = hdd_ctx->mac_handle;
96 current_roam_state =
97 sme_get_current_roam_state(mac_handle, adapter->session_id);
98 status = sme_stop_roaming(mac_handle, adapter->session_id,
99 eCsrHddIssued);
100 if (status != QDF_STATUS_SUCCESS) {
101 hdd_err("Enable/Disable roaming failed");
102 return -EINVAL;
103 }
104
105 status = sme_ps_enable_disable(mac_handle, adapter->session_id,
106 SME_PS_DISABLE);
107 if (status != QDF_STATUS_SUCCESS) {
108 hdd_err("Enable/Disable power save failed");
109 /* restore previous roaming setting */
110 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
111 current_roam_state == eCSR_ROAMING_STATE_JOINED)
112 status = sme_start_roaming(mac_handle,
113 adapter->session_id,
114 eCsrHddIssued);
115 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
116 current_roam_state == eCSR_ROAMING_STATE_IDLE)
117 status = sme_stop_roaming(mac_handle,
118 adapter->session_id,
119 eCsrHddIssued);
120
121 if (status != QDF_STATUS_SUCCESS)
122 hdd_err("Restoring roaming state failed");
123
124 return -EINVAL;
125 }
126 return 0;
127}
128
129int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
130 struct wireless_dev *wdev,
131 const void *data,
132 int data_len)
133{
134 int ret;
135
136 cds_ssr_protect(__func__);
137 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
138 cds_ssr_unprotect(__func__);
139
140 return ret;
141}
142