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