1 /*
2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: wlan_hdd_ota_test.c
22 *
23 * WLAN OTA test functions
24 *
25 */
26
27 #include "osif_sync.h"
28 #include <wlan_hdd_includes.h>
29 #include <linux/netdevice.h>
30 #include <linux/skbuff.h>
31 #include <linux/etherdevice.h>
32 #include <linux/if_ether.h>
33 #include <sme_power_save_api.h>
34 #include <wlan_hdd_ota_test.h>
35
36 const struct nla_policy qca_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 */
__wlan_hdd_cfg80211_set_ota_test(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)50 static 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 = sme_get_current_roam_state(
97 mac_handle, adapter->deflink->vdev_id);
98 status = sme_stop_roaming(mac_handle, adapter->deflink->vdev_id,
99 REASON_SME_ISSUED, RSO_INVALID_REQUESTOR);
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->deflink->vdev_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->deflink->vdev_id,
114 REASON_SME_ISSUED,
115 RSO_INVALID_REQUESTOR);
116 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
117 current_roam_state == eCSR_ROAMING_STATE_IDLE)
118 status = sme_stop_roaming(mac_handle,
119 adapter->deflink->vdev_id,
120 REASON_SME_ISSUED,
121 RSO_INVALID_REQUESTOR);
122
123 if (status != QDF_STATUS_SUCCESS)
124 hdd_err("Restoring roaming state failed");
125
126 return -EINVAL;
127 }
128 return 0;
129 }
130
wlan_hdd_cfg80211_set_ota_test(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)131 int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
132 struct wireless_dev *wdev,
133 const void *data,
134 int data_len)
135 {
136 struct osif_vdev_sync *vdev_sync;
137 int errno;
138
139 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
140 if (errno)
141 return errno;
142
143 errno = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
144
145 osif_vdev_sync_op_stop(vdev_sync);
146
147 return errno;
148 }
149
150