| /* |
| * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /** |
| * DOC: wlan_hdd_hostapd_wext.c |
| * |
| * Linux Wireless Extensions Implementation |
| */ |
| |
| #include "osif_sync.h" |
| #include <wlan_hdd_hostapd_wext.h> |
| #include <wlan_hdd_includes.h> |
| #include <qc_sap_ioctl.h> |
| #include <wlan_hdd_green_ap.h> |
| #include <wlan_hdd_hostapd.h> |
| #include <wlan_hdd_ioctl.h> |
| #include <wlan_hdd_stats.h> |
| #include "wlan_hdd_p2p.h" |
| #include "wma.h" |
| #ifdef WLAN_DEBUG |
| #include "wma_api.h" |
| #endif |
| #include "wlan_hdd_power.h" |
| #include "wlan_policy_mgr_ucfg.h" |
| #include <cdp_txrx_stats.h> |
| #include "wlan_dfs_utils_api.h" |
| #include <wlan_ipa_ucfg_api.h> |
| #include <wlan_cfg80211_mc_cp_stats.h> |
| #include "wlan_mlme_ucfg_api.h" |
| #include "wlan_reg_ucfg_api.h" |
| #define WE_WLAN_VERSION 1 |
| |
| /* WEXT limitation: MAX allowed buf len for any * |
| * IW_PRIV_TYPE_CHAR is 2Kbytes * |
| */ |
| #define WE_SAP_MAX_STA_INFO 0x7FF |
| |
| #define RC_2_RATE_IDX(_rc) ((_rc) & 0x7) |
| #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) |
| #define RC_2_RATE_IDX_11AC(_rc) ((_rc) & 0xf) |
| #define HT_RC_2_STREAMS_11AC(_rc) ((((_rc) & 0x30) >> 4) + 1) |
| |
| static int hdd_sap_get_chan_width(struct hdd_adapter *adapter, int *value) |
| { |
| struct sap_context *sap_ctx; |
| struct hdd_hostapd_state *hostapdstate; |
| |
| hdd_enter(); |
| hostapdstate = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); |
| |
| if (hostapdstate->bss_state != BSS_START) { |
| *value = -EINVAL; |
| return -EINVAL; |
| } |
| |
| sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter); |
| |
| *value = wlansap_get_chan_width(sap_ctx); |
| hdd_debug("chan_width = %d", *value); |
| |
| return 0; |
| } |
| |
| int |
| static __iw_softap_get_ini_cfg(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| struct hdd_context *hdd_ctx; |
| int ret; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (ret != 0) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| hdd_debug("Printing CLD global INI Config"); |
| hdd_cfg_get_global_config(hdd_ctx, extra, QCSAP_IOCTL_MAX_STR_LEN); |
| wrqu->data.length = strlen(extra) + 1; |
| |
| return 0; |
| } |
| |
| int |
| static iw_softap_get_ini_cfg(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_get_ini_cfg(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| /** |
| * iw_softap_set_two_ints_getnone() - Generic "set two integer" ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_softap_set_two_ints_getnone(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| int ret; |
| int *value = (int *)extra; |
| int sub_cmd = value[0]; |
| struct hdd_context *hdd_ctx; |
| struct cdp_vdev *vdev = NULL; |
| struct cdp_pdev *pdev = NULL; |
| void *soc = NULL; |
| struct cdp_txrx_stats_req req = {0}; |
| uint8_t count = 0; |
| struct hdd_station_info *sta_info; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (ret != 0) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| switch (sub_cmd) { |
| case QCSAP_PARAM_SET_TXRX_STATS: |
| { |
| ret = cds_get_datapath_handles(&soc, &pdev, &vdev, |
| adapter->vdev_id); |
| if (ret != 0) { |
| hdd_err("Invalid Handles"); |
| break; |
| } |
| req.stats = value[1]; |
| req.mac_id = value[2]; |
| hdd_info("QCSAP_PARAM_SET_TXRX_STATS stats_id: %d mac_id: %d", |
| req.stats, req.mac_id); |
| sta_info = adapter->sta_info; |
| if (value[1] == CDP_TXRX_STATS_28) { |
| req.peer_addr = (char *)&adapter->mac_addr; |
| ret = cdp_txrx_stats_request(soc, vdev, &req); |
| |
| for (count = 0; count < WLAN_MAX_STA_COUNT; count++) { |
| if (sta_info->in_use) { |
| hdd_debug("sta: %d: bss_id: %pM", |
| sta_info->sta_id, |
| (void *)&sta_info->sta_mac); |
| req.peer_addr = |
| (char *)&sta_info->sta_mac; |
| ret = cdp_txrx_stats_request(soc, vdev, |
| &req); |
| } |
| |
| sta_info++; |
| } |
| } else { |
| ret = cdp_txrx_stats_request(soc, vdev, &req); |
| } |
| |
| break; |
| } |
| |
| /* Firmware debug log */ |
| case QCSAP_IOCTL_SET_FW_CRASH_INJECT: |
| ret = hdd_crash_inject(adapter, value[1], value[2]); |
| break; |
| |
| case QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL: |
| hdd_set_dump_dp_trace(value[1], value[2]); |
| break; |
| |
| case QCSAP_ENABLE_FW_PROFILE: |
| hdd_debug("QCSAP_ENABLE_FW_PROFILE: %d %d", |
| value[1], value[2]); |
| ret = wma_cli_set2_command(adapter->vdev_id, |
| WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, |
| value[1], value[2], DBG_CMD); |
| break; |
| |
| case QCSAP_SET_FW_PROFILE_HIST_INTVL: |
| hdd_debug("QCSAP_SET_FW_PROFILE_HIST_INTVL: %d %d", |
| value[1], value[2]); |
| ret = wma_cli_set2_command(adapter->vdev_id, |
| WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, |
| value[1], value[2], DBG_CMD); |
| break; |
| |
| case QCSAP_SET_WLAN_SUSPEND: |
| hdd_info("SAP unit-test suspend(%d, %d)", value[1], value[2]); |
| ret = hdd_wlan_fake_apps_suspend(hdd_ctx->wiphy, dev, |
| value[1], value[2]); |
| break; |
| |
| case QCSAP_SET_WLAN_RESUME: |
| ret = hdd_wlan_fake_apps_resume(hdd_ctx->wiphy, dev); |
| break; |
| |
| case QCSAP_SET_BA_AGEING_TIMEOUT: |
| hdd_info("QCSAP_SET_BA_AGEING_TIMEOUT: AC[%d] timeout[%d]", |
| value[1], value[2]); |
| ret = cds_get_datapath_handles(&soc, &pdev, &vdev, |
| adapter->vdev_id); |
| if (ret != 0) { |
| hdd_err("Invalid Handles"); |
| break; |
| } |
| /* |
| * value[1] : suppose to be access class, value between[0-3] |
| * value[2]: suppose to be duration in seconds |
| */ |
| cdp_set_ba_timeout(soc, value[1], value[2]); |
| break; |
| |
| default: |
| hdd_err("Invalid IOCTL command: %d", sub_cmd); |
| break; |
| } |
| |
| return ret; |
| } |
| |
| static int iw_softap_set_two_ints_getnone(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_set_two_ints_getnone(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static void print_mac_list(struct qdf_mac_addr *macList, uint8_t size) |
| { |
| int i; |
| uint8_t *macArray; |
| |
| for (i = 0; i < size; i++) { |
| macArray = (macList + i)->bytes; |
| pr_info("ACL entry %i - "QDF_MAC_ADDR_STR"\n", |
| i, QDF_MAC_ADDR_ARRAY(macArray)); |
| } |
| } |
| |
| static QDF_STATUS hdd_print_acl(struct hdd_adapter *adapter) |
| { |
| eSapMacAddrACL acl_mode; |
| struct qdf_mac_addr maclist[MAX_ACL_MAC_ADDRESS]; |
| uint8_t listnum; |
| struct sap_context *sap_ctx; |
| |
| sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter); |
| qdf_mem_zero(&maclist[0], sizeof(maclist)); |
| if (QDF_STATUS_SUCCESS == wlansap_get_acl_mode(sap_ctx, &acl_mode)) { |
| pr_info("******** ACL MODE *********\n"); |
| switch (acl_mode) { |
| case eSAP_ACCEPT_UNLESS_DENIED: |
| pr_info("ACL Mode = ACCEPT_UNLESS_DENIED\n"); |
| break; |
| case eSAP_DENY_UNLESS_ACCEPTED: |
| pr_info("ACL Mode = DENY_UNLESS_ACCEPTED\n"); |
| break; |
| case eSAP_SUPPORT_ACCEPT_AND_DENY: |
| pr_info("ACL Mode = ACCEPT_AND_DENY\n"); |
| break; |
| case eSAP_ALLOW_ALL: |
| pr_info("ACL Mode = ALLOW_ALL\n"); |
| break; |
| default: |
| pr_info("Invalid SAP ACL Mode = %d\n", acl_mode); |
| return QDF_STATUS_E_FAILURE; |
| } |
| } else { |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (QDF_STATUS_SUCCESS == wlansap_get_acl_accept_list(sap_ctx, |
| &maclist[0], |
| &listnum)) { |
| pr_info("******* WHITE LIST ***********\n"); |
| if (listnum <= MAX_ACL_MAC_ADDRESS) |
| print_mac_list(&maclist[0], listnum); |
| } else { |
| return QDF_STATUS_E_FAILURE; |
| } |
| |
| if (QDF_STATUS_SUCCESS == wlansap_get_acl_deny_list(sap_ctx, |
| &maclist[0], |
| &listnum)) { |
| pr_info("******* BLACK LIST ***********\n"); |
| if (listnum <= MAX_ACL_MAC_ADDRESS) |
| print_mac_list(&maclist[0], listnum); |
| } else { |
| return QDF_STATUS_E_FAILURE; |
| } |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| /** |
| * hdd_get_aid_rc() - Get AID and rate code passed from user |
| * @aid: pointer to AID |
| * @rc: pointer to rate code |
| * @set_value: value passed from user |
| * |
| * If target is 11ax capable, set_value will have AID left shifted 16 bits |
| * and 16 bits for rate code. If the target is not 11ax capable, rate code |
| * will only be 8 bits. |
| * |
| * Return: None |
| */ |
| static void hdd_get_aid_rc(uint8_t *aid, uint16_t *rc, int set_value) |
| { |
| uint8_t rc_bits; |
| |
| if (sme_is_feature_supported_by_fw(DOT11AX)) |
| rc_bits = 16; |
| else |
| rc_bits = 8; |
| |
| *aid = set_value >> rc_bits; |
| *rc = set_value & ((1 << (rc_bits + 1)) - 1); |
| } |
| |
| /** |
| * hdd_set_peer_rate() - set peer rate |
| * @adapter: adapter being modified |
| * @set_value: rate code with AID |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int hdd_set_peer_rate(struct hdd_adapter *adapter, int set_value) |
| { |
| uint8_t aid, *peer_mac; |
| uint16_t rc; |
| QDF_STATUS status; |
| |
| if (adapter->device_mode != QDF_SAP_MODE) { |
| hdd_err("Invalid devicde mode - %d", adapter->device_mode); |
| return -EINVAL; |
| } |
| |
| hdd_get_aid_rc(&aid, &rc, set_value); |
| |
| if ((adapter->sta_info[aid].in_use) && |
| (OL_TXRX_PEER_STATE_CONN == adapter->sta_info[aid].peer_state)) { |
| peer_mac = |
| (uint8_t *)&(adapter->sta_info[aid].sta_mac.bytes[0]); |
| hdd_info("Peer AID: %d MAC_ADDR: "QDF_MAC_ADDR_STR, |
| aid, QDF_MAC_ADDR_ARRAY(peer_mac)); |
| } else { |
| hdd_err("No matching peer found for AID: %d", aid); |
| return -EINVAL; |
| } |
| |
| status = sme_set_peer_param(peer_mac, WMI_PEER_PARAM_FIXED_RATE, |
| rc, adapter->vdev_id); |
| if (status != QDF_STATUS_SUCCESS) { |
| hdd_err("Failed to set peer fixed rate - status: %d", status); |
| return -EIO; |
| } |
| |
| return 0; |
| } |
| |
| int |
| static __iw_softap_setparam(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| mac_handle_t mac_handle; |
| int *value = (int *)extra; |
| int sub_cmd = value[0]; |
| int set_value = value[1]; |
| QDF_STATUS status; |
| int ret = 0; |
| struct hdd_context *hdd_ctx; |
| bool bval = false; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return -EINVAL; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| mac_handle = hdd_ctx->mac_handle; |
| if (!mac_handle) { |
| hdd_err("mac handle is null"); |
| return -EINVAL; |
| } |
| |
| switch (sub_cmd) { |
| case QCASAP_SET_RADAR_DBG: |
| hdd_debug("QCASAP_SET_RADAR_DBG called with: value: %x", |
| set_value); |
| wlan_sap_enable_phy_error_logs(mac_handle, set_value); |
| break; |
| |
| case QCSAP_PARAM_CLR_ACL: |
| if (QDF_STATUS_SUCCESS != wlansap_clear_acl( |
| WLAN_HDD_GET_SAP_CTX_PTR(adapter))) { |
| ret = -EIO; |
| } |
| break; |
| |
| case QCSAP_PARAM_ACL_MODE: |
| if ((eSAP_ALLOW_ALL < (eSapMacAddrACL) set_value) || |
| (eSAP_ACCEPT_UNLESS_DENIED > (eSapMacAddrACL) set_value)) { |
| hdd_err("Invalid ACL Mode value: %d", set_value); |
| ret = -EINVAL; |
| } else { |
| wlansap_set_acl_mode( |
| WLAN_HDD_GET_SAP_CTX_PTR(adapter), |
| set_value); |
| } |
| break; |
| |
| case QCSAP_PARAM_SET_CHANNEL_CHANGE: |
| if ((QDF_SAP_MODE == adapter->device_mode) || |
| (QDF_P2P_GO_MODE == adapter->device_mode)) { |
| wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, |
| adapter->vdev_id, |
| CSA_REASON_USER_INITIATED); |
| hdd_debug("SET Channel Change to new channel= %d", |
| set_value); |
| ret = hdd_softap_set_channel_change(dev, set_value, |
| CH_WIDTH_MAX, |
| false); |
| } else { |
| hdd_err("Channel Change Failed, Device in test mode"); |
| ret = -EINVAL; |
| } |
| break; |
| |
| case QCSAP_PARAM_CONC_SYSTEM_PREF: |
| hdd_debug("New preference: %d", set_value); |
| ucfg_policy_mgr_set_sys_pref(hdd_ctx->psoc, set_value); |
| break; |
| |
| case QCSAP_PARAM_MAX_ASSOC: |
| if (WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) { |
| hdd_err("Invalid setMaxAssoc value %d", |
| set_value); |
| ret = -EINVAL; |
| } else { |
| if (WNI_CFG_ASSOC_STA_LIMIT_STAMAX < set_value) { |
| hdd_warn("setMaxAssoc %d > max allowed %d.", |
| set_value, |
| WNI_CFG_ASSOC_STA_LIMIT_STAMAX); |
| hdd_warn("Setting it to max allowed and continuing"); |
| set_value = WNI_CFG_ASSOC_STA_LIMIT_STAMAX; |
| } |
| if (ucfg_mlme_set_assoc_sta_limit(hdd_ctx->psoc, |
| set_value) != |
| QDF_STATUS_SUCCESS) { |
| hdd_err("CFG_ASSOC_STA_LIMIT failed"); |
| ret = -EIO; |
| } |
| |
| } |
| break; |
| |
| case QCSAP_PARAM_HIDE_SSID: |
| { |
| QDF_STATUS status; |
| |
| /* |
| * Reject hidden ssid param update if reassoc in progress on |
| * any adapter. sme_is_any_session_in_middle_of_roaming is for |
| * LFR2 and hdd_is_roaming_in_progress is for LFR3 |
| */ |
| if (hdd_is_roaming_in_progress(hdd_ctx) || |
| sme_is_any_session_in_middle_of_roaming(mac_handle)) { |
| hdd_info("Reassociation in progress"); |
| return -EINVAL; |
| } |
| |
| /* |
| * Disable Roaming on all adapters before start of |
| * start of Hidden ssid connection |
| */ |
| wlan_hdd_disable_roaming(adapter, RSO_START_BSS); |
| |
| status = sme_update_session_param(mac_handle, |
| adapter->vdev_id, |
| SIR_PARAM_SSID_HIDDEN, set_value); |
| if (QDF_STATUS_SUCCESS != status) { |
| hdd_err("QCSAP_PARAM_HIDE_SSID failed"); |
| wlan_hdd_enable_roaming(adapter, RSO_START_BSS); |
| return -EIO; |
| } |
| break; |
| } |
| case QCSAP_PARAM_SET_MC_RATE: |
| { |
| tSirRateUpdateInd rate_update = {0}; |
| |
| hdd_debug("MC Target rate %d", set_value); |
| qdf_copy_macaddr(&rate_update.bssid, |
| &adapter->mac_addr); |
| status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval); |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| hdd_err("unable to get vht_enable2x2"); |
| ret = -1; |
| } |
| rate_update.nss = (bval == 0) ? 0 : 1; |
| |
| rate_update.dev_mode = adapter->device_mode; |
| rate_update.mcastDataRate24GHz = set_value; |
| rate_update.mcastDataRate24GHzTxFlag = 1; |
| rate_update.mcastDataRate5GHz = set_value; |
| rate_update.bcastDataRate = -1; |
| status = sme_send_rate_update_ind(mac_handle, &rate_update); |
| if (QDF_STATUS_SUCCESS != status) { |
| hdd_err("SET_MC_RATE failed"); |
| ret = -1; |
| } |
| break; |
| } |
| |
| case QCSAP_PARAM_SET_TXRX_FW_STATS: |
| { |
| hdd_debug("QCSAP_PARAM_SET_TXRX_FW_STATS val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMA_VDEV_TXRX_FWSTATS_ENABLE_CMDID, |
| set_value, VDEV_CMD); |
| break; |
| } |
| |
| /* Firmware debug log */ |
| case QCSAP_DBGLOG_LOG_LEVEL: |
| { |
| hdd_debug("QCSAP_DBGLOG_LOG_LEVEL val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_LOG_LEVEL, |
| set_value, DBG_CMD); |
| break; |
| } |
| |
| case QCSAP_DBGLOG_VAP_ENABLE: |
| { |
| hdd_debug("QCSAP_DBGLOG_VAP_ENABLE val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_VAP_ENABLE, |
| set_value, DBG_CMD); |
| break; |
| } |
| |
| case QCSAP_DBGLOG_VAP_DISABLE: |
| { |
| hdd_debug("QCSAP_DBGLOG_VAP_DISABLE val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_VAP_DISABLE, |
| set_value, DBG_CMD); |
| break; |
| } |
| |
| case QCSAP_DBGLOG_MODULE_ENABLE: |
| { |
| hdd_debug("QCSAP_DBGLOG_MODULE_ENABLE val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_MODULE_ENABLE, |
| set_value, DBG_CMD); |
| break; |
| } |
| |
| case QCSAP_DBGLOG_MODULE_DISABLE: |
| { |
| hdd_debug("QCSAP_DBGLOG_MODULE_DISABLE val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_MODULE_DISABLE, |
| set_value, DBG_CMD); |
| break; |
| } |
| |
| case QCSAP_DBGLOG_MOD_LOG_LEVEL: |
| { |
| hdd_debug("QCSAP_DBGLOG_MOD_LOG_LEVEL val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_MOD_LOG_LEVEL, |
| set_value, DBG_CMD); |
| break; |
| } |
| |
| case QCSAP_DBGLOG_TYPE: |
| { |
| hdd_debug("QCSAP_DBGLOG_TYPE val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_TYPE, |
| set_value, DBG_CMD); |
| break; |
| } |
| case QCSAP_DBGLOG_REPORT_ENABLE: |
| { |
| hdd_debug("QCSAP_DBGLOG_REPORT_ENABLE val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_DBGLOG_REPORT_ENABLE, |
| set_value, DBG_CMD); |
| break; |
| } |
| case QCSAP_PARAM_SET_MCC_CHANNEL_LATENCY: |
| { |
| wlan_hdd_set_mcc_latency(adapter, set_value); |
| break; |
| } |
| |
| case QCSAP_PARAM_SET_MCC_CHANNEL_QUOTA: |
| { |
| hdd_debug("iwpriv cmd to set MCC quota value %dms", |
| set_value); |
| ret = wlan_hdd_go_set_mcc_p2p_quota(adapter, |
| set_value); |
| break; |
| } |
| |
| case QCASAP_TXRX_FWSTATS_RESET: |
| { |
| hdd_debug("WE_TXRX_FWSTATS_RESET val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMA_VDEV_TXRX_FWSTATS_RESET_CMDID, |
| set_value, VDEV_CMD); |
| break; |
| } |
| |
| case QCSAP_PARAM_RTSCTS: |
| { |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_ENABLE_RTSCTS, |
| set_value, VDEV_CMD); |
| if (ret) { |
| hdd_err("FAILED TO SET RTSCTS at SAP"); |
| ret = -EIO; |
| } |
| break; |
| } |
| case QCASAP_SET_11N_RATE: |
| { |
| uint8_t preamble = 0, nss = 0, rix = 0; |
| struct sap_config *config = |
| &adapter->session.ap.sap_config; |
| |
| hdd_debug("SET_HT_RATE val %d", set_value); |
| |
| if (set_value != 0xff) { |
| rix = RC_2_RATE_IDX(set_value); |
| if (set_value & 0x80) { |
| if (config->SapHw_mode == |
| eCSR_DOT11_MODE_11b |
| || config->SapHw_mode == |
| eCSR_DOT11_MODE_11b_ONLY |
| || config->SapHw_mode == |
| eCSR_DOT11_MODE_11g |
| || config->SapHw_mode == |
| eCSR_DOT11_MODE_11g_ONLY |
| || config->SapHw_mode == |
| eCSR_DOT11_MODE_abg |
| || config->SapHw_mode == |
| eCSR_DOT11_MODE_11a) { |
| hdd_err("Not valid mode for HT"); |
| ret = -EIO; |
| break; |
| } |
| preamble = WMI_RATE_PREAMBLE_HT; |
| nss = HT_RC_2_STREAMS(set_value) - 1; |
| } else if (set_value & 0x10) { |
| if (config->SapHw_mode == |
| eCSR_DOT11_MODE_11a) { |
| hdd_err("Not valid for cck"); |
| ret = -EIO; |
| break; |
| } |
| preamble = WMI_RATE_PREAMBLE_CCK; |
| /* Enable Short preamble always |
| * for CCK except 1mbps |
| */ |
| if (rix != 0x3) |
| rix |= 0x4; |
| } else { |
| if (config->SapHw_mode == |
| eCSR_DOT11_MODE_11b |
| || config->SapHw_mode == |
| eCSR_DOT11_MODE_11b_ONLY) { |
| hdd_err("Not valid for OFDM"); |
| ret = -EIO; |
| break; |
| } |
| preamble = WMI_RATE_PREAMBLE_OFDM; |
| } |
| set_value = hdd_assemble_rate_code(preamble, nss, rix); |
| } |
| hdd_debug("SET_HT_RATE val %d rix %d preamble %x nss %d", |
| set_value, rix, preamble, nss); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_FIXED_RATE, |
| set_value, VDEV_CMD); |
| break; |
| } |
| |
| case QCASAP_SET_VHT_RATE: |
| { |
| uint8_t preamble = 0, nss = 0, rix = 0; |
| struct sap_config *config = |
| &adapter->session.ap.sap_config; |
| |
| if (config->SapHw_mode != eCSR_DOT11_MODE_11ac && |
| config->SapHw_mode != eCSR_DOT11_MODE_11ac_ONLY) { |
| hdd_err("SET_VHT_RATE: SapHw_mode= 0x%x, ch_freq: %d", |
| config->SapHw_mode, config->chan_freq); |
| ret = -EIO; |
| break; |
| } |
| |
| if (set_value != 0xff) { |
| rix = RC_2_RATE_IDX_11AC(set_value); |
| preamble = WMI_RATE_PREAMBLE_VHT; |
| nss = HT_RC_2_STREAMS_11AC(set_value) - 1; |
| |
| set_value = hdd_assemble_rate_code(preamble, nss, rix); |
| } |
| hdd_debug("SET_VHT_RATE val %d rix %d preamble %x nss %d", |
| set_value, rix, preamble, nss); |
| |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_FIXED_RATE, |
| set_value, VDEV_CMD); |
| break; |
| } |
| |
| case QCASAP_SHORT_GI: |
| { |
| hdd_debug("QCASAP_SET_SHORT_GI val %d", set_value); |
| ret = hdd_we_set_short_gi(adapter, set_value); |
| if (ret) |
| hdd_err("Failed to set ShortGI value ret: %d", ret); |
| break; |
| } |
| |
| case QCSAP_SET_AMPDU: |
| { |
| hdd_debug("QCSAP_SET_AMPDU %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| GEN_VDEV_PARAM_AMPDU, |
| set_value, GEN_CMD); |
| break; |
| } |
| |
| case QCSAP_SET_AMSDU: |
| { |
| hdd_debug("QCSAP_SET_AMSDU %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| GEN_VDEV_PARAM_AMSDU, |
| set_value, GEN_CMD); |
| break; |
| } |
| case QCSAP_GTX_HT_MCS: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_HT_MCS %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_HT_MCS, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_VHT_MCS: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_VHT_MCS %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_VHT_MCS, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_USRCFG: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_USR_CFG %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_USR_CFG, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_THRE: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_THRE %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_THRE, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_MARGIN: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_MARGIN %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_MARGIN, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_STEP: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_STEP %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_STEP, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_MINTPC: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_MINTPC %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_MINTPC, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_BWMASK: |
| { |
| hdd_debug("WMI_VDEV_PARAM_GTX_BWMASK %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_BW_MASK, |
| set_value, GTX_CMD); |
| break; |
| } |
| |
| case QCASAP_SET_TM_LEVEL: |
| { |
| hdd_debug("Set Thermal Mitigation Level %d", set_value); |
| (void)sme_set_thermal_level(mac_handle, set_value); |
| break; |
| } |
| |
| case QCASAP_SET_DFS_IGNORE_CAC: |
| { |
| hdd_debug("Set Dfs ignore CAC %d", set_value); |
| |
| if (adapter->device_mode != QDF_SAP_MODE) |
| return -EINVAL; |
| |
| ret = wlansap_set_dfs_ignore_cac(mac_handle, set_value); |
| break; |
| } |
| |
| case QCASAP_SET_DFS_TARGET_CHNL: |
| { |
| hdd_debug("Set Dfs target channel %d", set_value); |
| |
| if (adapter->device_mode != QDF_SAP_MODE) |
| return -EINVAL; |
| |
| ret = wlansap_set_dfs_target_chnl(mac_handle, set_value); |
| break; |
| } |
| |
| case QCASAP_SET_HE_BSS_COLOR: |
| if (adapter->device_mode != QDF_SAP_MODE) |
| return -EINVAL; |
| |
| status = sme_set_he_bss_color(mac_handle, adapter->vdev_id, |
| set_value); |
| if (QDF_STATUS_SUCCESS != status) { |
| hdd_err("SET_HE_BSS_COLOR failed"); |
| return -EIO; |
| } |
| break; |
| case QCASAP_SET_DFS_NOL: |
| wlansap_set_dfs_nol( |
| WLAN_HDD_GET_SAP_CTX_PTR(adapter), |
| (eSapDfsNolType) set_value); |
| break; |
| |
| case QCASAP_SET_RADAR_CMD: |
| { |
| struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter); |
| uint8_t ch = ap_ctx->operating_channel; |
| struct wlan_objmgr_pdev *pdev; |
| struct radar_found_info radar; |
| |
| hdd_debug("Set QCASAP_SET_RADAR_CMD val %d", set_value); |
| |
| pdev = hdd_ctx->pdev; |
| if (!pdev) { |
| hdd_err("null pdev"); |
| return -EINVAL; |
| } |
| |
| qdf_mem_zero(&radar, sizeof(radar)); |
| if (wlan_reg_is_dfs_ch(pdev, ch)) |
| tgt_dfs_process_radar_ind(pdev, &radar); |
| else |
| hdd_err("Ignore set radar, op ch(%d) is not dfs", ch); |
| |
| break; |
| } |
| case QCASAP_TX_CHAINMASK_CMD: |
| { |
| hdd_debug("QCASAP_TX_CHAINMASK_CMD val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_PDEV_PARAM_TX_CHAIN_MASK, |
| set_value, PDEV_CMD); |
| ret = hdd_set_antenna_mode(adapter, hdd_ctx, set_value); |
| break; |
| } |
| |
| case QCASAP_RX_CHAINMASK_CMD: |
| { |
| hdd_debug("QCASAP_RX_CHAINMASK_CMD val %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_PDEV_PARAM_RX_CHAIN_MASK, |
| set_value, PDEV_CMD); |
| ret = hdd_set_antenna_mode(adapter, hdd_ctx, set_value); |
| break; |
| } |
| |
| case QCASAP_NSS_CMD: |
| { |
| hdd_debug("QCASAP_NSS_CMD val %d", set_value); |
| hdd_update_nss(adapter, set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_NSS, |
| set_value, VDEV_CMD); |
| break; |
| } |
| |
| case QCSAP_IPA_UC_STAT: |
| { |
| /* If input value is non-zero get stats */ |
| switch (set_value) { |
| case 1: |
| ucfg_ipa_uc_stat(hdd_ctx->pdev); |
| break; |
| case 2: |
| ucfg_ipa_uc_info(hdd_ctx->pdev); |
| break; |
| case 3: |
| ucfg_ipa_uc_rt_debug_host_dump(hdd_ctx->pdev); |
| break; |
| case 4: |
| ucfg_ipa_dump_info(hdd_ctx->pdev); |
| break; |
| default: |
| /* place holder for stats clean up |
| * Stats clean not implemented yet on FW and IPA |
| */ |
| break; |
| } |
| return ret; |
| } |
| |
| case QCASAP_SET_PHYMODE: |
| ret = wlan_hdd_update_phymode(adapter, set_value); |
| break; |
| |
| case QCASAP_DUMP_STATS: |
| { |
| hdd_debug("QCASAP_DUMP_STATS val %d", set_value); |
| ret = hdd_wlan_dump_stats(adapter, set_value); |
| break; |
| } |
| case QCASAP_CLEAR_STATS: |
| { |
| void *soc = cds_get_context(QDF_MODULE_ID_SOC); |
| |
| hdd_debug("QCASAP_CLEAR_STATS val %d", set_value); |
| switch (set_value) { |
| case CDP_HDD_STATS: |
| memset(&adapter->stats, 0, |
| sizeof(adapter->stats)); |
| memset(&adapter->hdd_stats, 0, |
| sizeof(adapter->hdd_stats)); |
| break; |
| case CDP_TXRX_HIST_STATS: |
| wlan_hdd_clear_tx_rx_histogram(hdd_ctx); |
| break; |
| case CDP_HDD_NETIF_OPER_HISTORY: |
| wlan_hdd_clear_netif_queue_history(hdd_ctx); |
| break; |
| case CDP_HIF_STATS: |
| hdd_clear_hif_stats(); |
| break; |
| default: |
| if (soc) |
| cdp_clear_stats(soc, set_value); |
| } |
| break; |
| } |
| case QCSAP_START_FW_PROFILING: |
| hdd_debug("QCSAP_START_FW_PROFILING %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_WLAN_PROFILE_TRIGGER_CMDID, |
| set_value, DBG_CMD); |
| break; |
| case QCASAP_PARAM_LDPC: |
| ret = hdd_set_ldpc(adapter, set_value); |
| break; |
| case QCASAP_PARAM_TX_STBC: |
| ret = hdd_set_tx_stbc(adapter, set_value); |
| break; |
| case QCASAP_PARAM_RX_STBC: |
| ret = hdd_set_rx_stbc(adapter, set_value); |
| break; |
| case QCASAP_SET_11AX_RATE: |
| ret = hdd_set_11ax_rate(adapter, set_value, |
| &adapter->session.ap. |
| sap_config); |
| break; |
| case QCASAP_SET_PEER_RATE: |
| ret = hdd_set_peer_rate(adapter, set_value); |
| break; |
| case QCASAP_PARAM_DCM: |
| hdd_debug("Set WMI_VDEV_PARAM_HE_DCM: %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_HE_DCM, set_value, |
| VDEV_CMD); |
| break; |
| case QCASAP_PARAM_RANGE_EXT: |
| hdd_debug("Set WMI_VDEV_PARAM_HE_RANGE_EXT: %d", set_value); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_HE_RANGE_EXT, |
| set_value, VDEV_CMD); |
| break; |
| case QCSAP_SET_DEFAULT_AMPDU: |
| hdd_debug("QCSAP_SET_DEFAULT_AMPDU val %d", set_value); |
| ret = wma_cli_set_command((int)adapter->vdev_id, |
| (int)WMI_PDEV_PARAM_MAX_MPDUS_IN_AMPDU, |
| set_value, PDEV_CMD); |
| break; |
| case QCSAP_ENABLE_RTS_BURSTING: |
| hdd_debug("QCSAP_ENABLE_RTS_BURSTING val %d", set_value); |
| ret = wma_cli_set_command((int)adapter->vdev_id, |
| (int)WMI_PDEV_PARAM_ENABLE_RTS_SIFS_BURSTING, |
| set_value, PDEV_CMD); |
| break; |
| case QCSAP_SET_BTCOEX_MODE: |
| ret = wlan_hdd_set_btcoex_mode(adapter, set_value); |
| break; |
| case QCSAP_SET_BTCOEX_LOW_RSSI_THRESHOLD: |
| ret = wlan_hdd_set_btcoex_rssi_threshold(adapter, set_value); |
| break; |
| default: |
| hdd_err("Invalid setparam command %d value %d", |
| sub_cmd, set_value); |
| ret = -EINVAL; |
| break; |
| } |
| hdd_exit(); |
| return ret; |
| } |
| |
| /** |
| * __iw_softap_get_three() - return three value to upper layer. |
| * @dev: pointer of net_device of this wireless card |
| * @info: meta data about Request sent |
| * @wrqu: include request info |
| * @extra: buf used for in/out |
| * |
| * Return: execute result |
| */ |
| static int __iw_softap_get_three(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| uint32_t *value = (uint32_t *)extra; |
| uint32_t sub_cmd = value[0]; |
| int ret = 0; /* success */ |
| struct hdd_context *hdd_ctx; |
| struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (ret != 0) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| switch (sub_cmd) { |
| case QCSAP_GET_TSF: |
| ret = hdd_indicate_tsf(adapter, value, 3); |
| break; |
| default: |
| hdd_err("Invalid getparam command: %d", sub_cmd); |
| ret = -EINVAL; |
| break; |
| } |
| return ret; |
| } |
| |
| |
| /** |
| * iw_softap_get_three() - return three value to upper layer. |
| * |
| * @dev: pointer of net_device of this wireless card |
| * @info: meta data about Request sent |
| * @wrqu: include request info |
| * @extra: buf used for in/Output |
| * |
| * Return: execute result |
| */ |
| static int iw_softap_get_three(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_get_three(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| int |
| static iw_softap_setparam(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_setparam(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| int |
| static __iw_softap_getparam(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| int *value = (int *)extra; |
| int sub_cmd = value[0]; |
| int ret; |
| struct hdd_context *hdd_ctx; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| switch (sub_cmd) { |
| case QCSAP_PARAM_MAX_ASSOC: |
| if (ucfg_mlme_set_assoc_sta_limit(hdd_ctx->psoc, *value) != |
| QDF_STATUS_SUCCESS) { |
| hdd_err("CFG_ASSOC_STA_LIMIT failed"); |
| ret = -EIO; |
| } |
| |
| break; |
| |
| case QCSAP_PARAM_GET_WLAN_DBG: |
| { |
| qdf_trace_display(); |
| *value = 0; |
| break; |
| } |
| |
| case QCSAP_PARAM_RTSCTS: |
| { |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_ENABLE_RTSCTS, |
| VDEV_CMD); |
| break; |
| } |
| |
| case QCASAP_SHORT_GI: |
| { |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_SGI, |
| VDEV_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_HT_MCS: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_HT_MCS"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_HT_MCS, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_VHT_MCS: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_VHT_MCS"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_VHT_MCS, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_USRCFG: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_USR_CFG"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_USR_CFG, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_THRE: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_THRE"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_THRE, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_MARGIN: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_MARGIN"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_MARGIN, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_STEP: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_STEP"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_STEP, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_MINTPC: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_MINTPC"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_MINTPC, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCSAP_GTX_BWMASK: |
| { |
| hdd_debug("GET WMI_VDEV_PARAM_GTX_BW_MASK"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_GTX_BW_MASK, |
| GTX_CMD); |
| break; |
| } |
| |
| case QCASAP_GET_DFS_NOL: |
| { |
| struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| struct wlan_objmgr_pdev *pdev; |
| |
| pdev = hdd_ctx->pdev; |
| if (!pdev) { |
| hdd_err("null pdev"); |
| return -EINVAL; |
| } |
| |
| utils_dfs_print_nol_channels(pdev); |
| } |
| break; |
| |
| case QCSAP_GET_ACL: |
| { |
| hdd_debug("QCSAP_GET_ACL"); |
| if (hdd_print_acl(adapter) != |
| QDF_STATUS_SUCCESS) { |
| hdd_err("QCSAP_GET_ACL returned Error: not completed"); |
| } |
| *value = 0; |
| break; |
| } |
| |
| case QCASAP_TX_CHAINMASK_CMD: |
| { |
| hdd_debug("QCASAP_TX_CHAINMASK_CMD"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_PDEV_PARAM_TX_CHAIN_MASK, |
| PDEV_CMD); |
| break; |
| } |
| |
| case QCASAP_RX_CHAINMASK_CMD: |
| { |
| hdd_debug("QCASAP_RX_CHAINMASK_CMD"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_PDEV_PARAM_RX_CHAIN_MASK, |
| PDEV_CMD); |
| break; |
| } |
| |
| case QCASAP_NSS_CMD: |
| { |
| hdd_debug("QCASAP_NSS_CMD"); |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_NSS, |
| VDEV_CMD); |
| break; |
| } |
| case QCSAP_CAP_TSF: |
| ret = hdd_capture_tsf(adapter, (uint32_t *)value, 1); |
| break; |
| case QCASAP_GET_TEMP_CMD: |
| { |
| hdd_debug("QCASAP_GET_TEMP_CMD"); |
| ret = wlan_hdd_get_temperature(adapter, value); |
| break; |
| } |
| case QCSAP_GET_FW_PROFILE_DATA: |
| hdd_debug("QCSAP_GET_FW_PROFILE_DATA"); |
| ret = wma_cli_set_command(adapter->vdev_id, |
| WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, |
| 0, DBG_CMD); |
| break; |
| case QCASAP_PARAM_LDPC: |
| { |
| ret = hdd_get_ldpc(adapter, value); |
| break; |
| } |
| case QCASAP_PARAM_TX_STBC: |
| { |
| ret = hdd_get_tx_stbc(adapter, value); |
| break; |
| } |
| case QCASAP_PARAM_RX_STBC: |
| { |
| ret = hdd_get_rx_stbc(adapter, value); |
| break; |
| } |
| case QCSAP_PARAM_CHAN_WIDTH: |
| { |
| ret = hdd_sap_get_chan_width(adapter, value); |
| break; |
| } |
| case QCASAP_PARAM_DCM: |
| { |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_HE_DCM, |
| VDEV_CMD); |
| break; |
| } |
| case QCASAP_PARAM_RANGE_EXT: |
| { |
| *value = wma_cli_get_command(adapter->vdev_id, |
| WMI_VDEV_PARAM_HE_RANGE_EXT, |
| VDEV_CMD); |
| break; |
| } |
| default: |
| hdd_err("Invalid getparam command: %d", sub_cmd); |
| ret = -EINVAL; |
| break; |
| |
| } |
| hdd_exit(); |
| return ret; |
| } |
| |
| int |
| static iw_softap_getparam(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_getparam(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| /* Usage: |
| * BLACK_LIST = 0 |
| * WHITE_LIST = 1 |
| * ADD MAC = 0 |
| * REMOVE MAC = 1 |
| * |
| * mac addr will be accepted as a 6 octet mac address with each octet |
| * inputted in hex for e.g. 00:0a:f5:11:22:33 will be represented as |
| * 0x00 0x0a 0xf5 0x11 0x22 0x33 while using this ioctl |
| * |
| * Syntax: |
| * iwpriv softap.0 modify_acl |
| * <6 octet mac addr> <list type> <cmd type> |
| * |
| * Examples: |
| * eg 1. to add a mac addr 00:0a:f5:89:89:90 to the black list |
| * iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 0 0 |
| * eg 2. to delete a mac addr 00:0a:f5:89:89:90 from white list |
| * iwpriv softap.0 modify_acl 0x00 0x0a 0xf5 0x89 0x89 0x90 1 1 |
| */ |
| static |
| int __iw_softap_modify_acl(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| uint8_t *value = (uint8_t *) extra; |
| uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; |
| int list_type, cmd, i; |
| int ret; |
| QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; |
| struct hdd_context *hdd_ctx; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) |
| peer_mac[i] = *(value + i); |
| |
| list_type = (int)(*(value + i)); |
| i++; |
| cmd = (int)(*(value + i)); |
| |
| hdd_debug("Modify ACL mac:" QDF_MAC_ADDR_STR " type: %d cmd: %d", |
| QDF_MAC_ADDR_ARRAY(peer_mac), list_type, cmd); |
| |
| qdf_status = wlansap_modify_acl( |
| WLAN_HDD_GET_SAP_CTX_PTR(adapter), |
| peer_mac, (eSapACLType) list_type, (eSapACLCmdType) cmd); |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| hdd_err("Modify ACL failed"); |
| ret = -EIO; |
| } |
| hdd_exit(); |
| return ret; |
| } |
| |
| static |
| int iw_softap_modify_acl(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_modify_acl(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| int |
| static __iw_softap_getchannel(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_context *hdd_ctx; |
| int *value = (int *)extra; |
| int ret; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| *value = 0; |
| if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) |
| *value = (WLAN_HDD_GET_AP_CTX_PTR( |
| adapter))->operating_channel; |
| hdd_exit(); |
| return 0; |
| } |
| |
| int |
| static iw_softap_getchannel(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_getchannel(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| int |
| static __iw_softap_set_max_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_context *hdd_ctx; |
| int *value = (int *)extra; |
| int set_value; |
| int ret; |
| struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT; |
| struct qdf_mac_addr selfMac = QDF_MAC_ADDR_BCAST_INIT; |
| |
| hdd_enter_dev(dev); |
| |
| if (!value) |
| return -ENOMEM; |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| /* Assign correct self MAC address */ |
| qdf_copy_macaddr(&bssid, &adapter->mac_addr); |
| qdf_copy_macaddr(&selfMac, &adapter->mac_addr); |
| |
| set_value = value[0]; |
| if (QDF_STATUS_SUCCESS != |
| sme_set_max_tx_power(hdd_ctx->mac_handle, bssid, |
| selfMac, set_value)) { |
| hdd_err("Setting maximum tx power failed"); |
| return -EIO; |
| } |
| hdd_exit(); |
| return 0; |
| } |
| |
| int |
| static iw_softap_set_max_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_set_max_tx_power(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| #ifndef REMOVE_PKT_LOG |
| int |
| static __iw_softap_set_pktlog(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = netdev_priv(dev); |
| struct hdd_context *hdd_ctx; |
| int *value = (int *)extra; |
| int ret; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| if (wrqu->data.length < 1 || wrqu->data.length > 2) { |
| hdd_err("pktlog: either 1 or 2 parameters are required"); |
| return -EINVAL; |
| } |
| |
| return hdd_process_pktlog_command(hdd_ctx, value[0], value[1]); |
| } |
| |
| int |
| static iw_softap_set_pktlog(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_set_pktlog(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| #else |
| int |
| static iw_softap_set_pktlog(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| return -EINVAL; |
| } |
| #endif |
| |
| int |
| static __iw_softap_set_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_context *hdd_ctx; |
| int *value = (int *)extra; |
| int set_value; |
| struct qdf_mac_addr bssid; |
| int ret; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| qdf_copy_macaddr(&bssid, &adapter->mac_addr); |
| |
| set_value = value[0]; |
| if (QDF_STATUS_SUCCESS != |
| sme_set_tx_power(hdd_ctx->mac_handle, adapter->vdev_id, bssid, |
| adapter->device_mode, set_value)) { |
| hdd_err("Setting tx power failed"); |
| return -EIO; |
| } |
| hdd_exit(); |
| return 0; |
| } |
| |
| int |
| static iw_softap_set_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_set_tx_power(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| int |
| static __iw_softap_getassoc_stamacaddr(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_station_info *sta_info = adapter->sta_info; |
| struct hdd_context *hdd_ctx; |
| char *buf; |
| int cnt = 0; |
| int left; |
| int ret; |
| /* maclist_index must be u32 to match userspace */ |
| u32 maclist_index; |
| |
| hdd_enter_dev(dev); |
| |
| /* |
| * NOTE WELL: this is a "get" ioctl but it uses an even ioctl |
| * number, and even numbered iocts are supposed to have "set" |
| * semantics. Hence the wireless extensions support in the kernel |
| * won't correctly copy the result to userspace, so the ioctl |
| * handler itself must copy the data. Output format is 32-bit |
| * record length, followed by 0 or more 6-byte STA MAC addresses. |
| * |
| * Further note that due to the incorrect semantics, the "iwpriv" |
| * userspace application is unable to correctly invoke this API, |
| * hence it is not registered in the hostapd_private_args. This |
| * API can only be invoked by directly invoking the ioctl() system |
| * call. |
| */ |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| /* make sure userspace allocated a reasonable buffer size */ |
| if (wrqu->data.length < sizeof(maclist_index)) { |
| hdd_err("invalid userspace buffer"); |
| return -EINVAL; |
| } |
| |
| /* allocate local buffer to build the response */ |
| buf = qdf_mem_malloc(wrqu->data.length); |
| if (!buf) |
| return -ENOMEM; |
| |
| /* start indexing beyond where the record count will be written */ |
| maclist_index = sizeof(maclist_index); |
| left = wrqu->data.length - maclist_index; |
| |
| spin_lock_bh(&adapter->sta_info_lock); |
| while ((cnt < WLAN_MAX_STA_COUNT) && (left >= QDF_MAC_ADDR_SIZE)) { |
| if ((sta_info[cnt].in_use) && |
| (!qdf_is_macaddr_broadcast(&sta_info[cnt].sta_mac))) { |
| memcpy(&buf[maclist_index], &(sta_info[cnt].sta_mac), |
| QDF_MAC_ADDR_SIZE); |
| maclist_index += QDF_MAC_ADDR_SIZE; |
| left -= QDF_MAC_ADDR_SIZE; |
| } |
| cnt++; |
| } |
| spin_unlock_bh(&adapter->sta_info_lock); |
| |
| *((u32 *) buf) = maclist_index; |
| wrqu->data.length = maclist_index; |
| if (copy_to_user(wrqu->data.pointer, buf, maclist_index)) { |
| hdd_err("failed to copy response to user buffer"); |
| ret = -EFAULT; |
| } |
| qdf_mem_free(buf); |
| hdd_exit(); |
| return ret; |
| } |
| |
| int |
| static iw_softap_getassoc_stamacaddr(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_getassoc_stamacaddr(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| /* Usage: |
| * mac addr will be accepted as a 6 octet mac address with each octet |
| * inputted in hex for e.g. 00:0a:f5:11:22:33 will be represented as |
| * 0x00 0x0a 0xf5 0x11 0x22 0x33 while using this ioctl |
| * |
| * Syntax: |
| * iwpriv softap.0 disassoc_sta <6 octet mac address> |
| * |
| * e.g. |
| * disassociate sta with mac addr 00:0a:f5:11:22:33 from softap |
| * iwpriv softap.0 disassoc_sta 0x00 0x0a 0xf5 0x11 0x22 0x33 |
| */ |
| |
| int |
| static __iw_softap_disassoc_sta(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_context *hdd_ctx; |
| uint8_t *peer_macaddr; |
| int ret; |
| struct csr_del_sta_params del_sta_params; |
| |
| hdd_enter_dev(dev); |
| |
| if (!capable(CAP_NET_ADMIN)) { |
| hdd_err("permission check failed"); |
| return -EPERM; |
| } |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| /* iwpriv tool or framework calls this ioctl with |
| * data passed in extra (less than 16 octets); |
| */ |
| peer_macaddr = (uint8_t *) (extra); |
| |
| hdd_debug("data " QDF_MAC_ADDR_STR, |
| QDF_MAC_ADDR_ARRAY(peer_macaddr)); |
| wlansap_populate_del_sta_params(peer_macaddr, |
| eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, |
| (SIR_MAC_MGMT_DISASSOC >> 4), |
| &del_sta_params); |
| hdd_softap_sta_disassoc(adapter, &del_sta_params); |
| |
| hdd_exit(); |
| return 0; |
| } |
| |
| int |
| static iw_softap_disassoc_sta(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_disassoc_sta(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| /** |
| * iw_get_char_setnone() - Generic "get char" private ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_char_setnone(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| int ret; |
| int sub_cmd = wrqu->data.flags; |
| struct hdd_context *hdd_ctx; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (ret != 0) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| switch (sub_cmd) { |
| case QCSAP_GET_STATS: |
| hdd_wlan_get_stats(adapter, &(wrqu->data.length), |
| extra, WE_MAX_STR_LEN); |
| break; |
| case QCSAP_LIST_FW_PROFILE: |
| hdd_wlan_list_fw_profile(&(wrqu->data.length), |
| extra, WE_MAX_STR_LEN); |
| break; |
| } |
| |
| hdd_exit(); |
| return ret; |
| } |
| |
| static int iw_get_char_setnone(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_get_char_setnone(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static int iw_get_channel_list(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| uint32_t num_channels = 0; |
| uint8_t i = 0; |
| uint8_t band_start_channel = MIN_24GHZ_CHANNEL; |
| uint8_t band_end_channel = MAX_5GHZ_CHANNEL; |
| struct hdd_adapter *hostapd_adapter = (netdev_priv(dev)); |
| struct channel_list_info *channel_list = |
| (struct channel_list_info *) extra; |
| bool enable_dfs_scan = true; |
| enum band_info cur_band = BAND_ALL; |
| struct hdd_context *hdd_ctx; |
| int ret; |
| bool is_dfs_mode_enabled = false; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| if (QDF_STATUS_SUCCESS != ucfg_reg_get_band(hdd_ctx->pdev, &cur_band)) { |
| hdd_err_rl("not able get the current frequency band"); |
| return -EIO; |
| } |
| |
| if (BAND_2G == cur_band) { |
| band_start_channel = MIN_24GHZ_CHANNEL; |
| band_end_channel = MAX_24GHZ_CHANNEL; |
| } else if (BAND_5G == cur_band) { |
| band_start_channel = MIN_5GHZ_CHANNEL; |
| band_end_channel = MAX_5GHZ_CHANNEL; |
| } |
| |
| if (cur_band != BAND_2G) |
| band_end_channel = MAX_5GHZ_CHANNEL; |
| ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc, |
| &enable_dfs_scan); |
| if (hostapd_adapter->device_mode == QDF_STA_MODE && |
| enable_dfs_scan) { |
| is_dfs_mode_enabled = true; |
| } else if (hostapd_adapter->device_mode == QDF_SAP_MODE) { |
| if (QDF_STATUS_SUCCESS != ucfg_mlme_get_dfs_master_capability( |
| hdd_ctx->psoc, &is_dfs_mode_enabled)) { |
| hdd_err_rl("Fail to get dfs master mode capability"); |
| return -EINVAL; |
| } |
| } |
| |
| hdd_debug_rl("curBand = %d, StartChannel = %hu, EndChannel = %hu, is_dfs_mode_enabled = %d", |
| cur_band, band_start_channel, band_end_channel, |
| is_dfs_mode_enabled); |
| |
| for (i = band_start_channel; i <= band_end_channel; i++) { |
| if ((CHANNEL_STATE_ENABLE == |
| wlan_reg_get_channel_state(hdd_ctx->pdev, |
| WLAN_REG_CH_NUM(i))) || |
| (is_dfs_mode_enabled && CHANNEL_STATE_DFS == |
| wlan_reg_get_channel_state(hdd_ctx->pdev, |
| WLAN_REG_CH_NUM(i)))) { |
| channel_list->channels[num_channels] = |
| WLAN_REG_CH_NUM(i); |
| num_channels++; |
| } |
| } |
| |
| hdd_debug_rl("number of channels %d", num_channels); |
| |
| channel_list->num_channels = num_channels; |
| wrqu->data.length = num_channels + 1; |
| hdd_exit(); |
| |
| return 0; |
| } |
| |
| int iw_get_channel_list_with_cc(struct net_device *dev, |
| mac_handle_t mac_handle, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| uint8_t i, len; |
| char *buf; |
| uint8_t ubuf[CFG_COUNTRY_CODE_LEN] = {0}; |
| uint8_t ubuf_len = CFG_COUNTRY_CODE_LEN; |
| struct channel_list_info channel_list; |
| |
| hdd_enter_dev(dev); |
| |
| memset(&channel_list, 0, sizeof(channel_list)); |
| |
| if (0 != iw_get_channel_list(dev, info, wrqu, (char *)&channel_list)) { |
| hdd_err_rl("GetChannelList Failed!!!"); |
| return -EINVAL; |
| } |
| buf = extra; |
| /* |
| * Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. |
| * Maximum buffer needed = 5 * number of channels. |
| * Check if sufficient buffer is available and then |
| * proceed to fill the buffer. |
| */ |
| if (WE_MAX_STR_LEN < (5 * CFG_VALID_CHANNEL_LIST_LEN)) { |
| hdd_err_rl("Insufficient Buffer to populate channel list"); |
| return -EINVAL; |
| } |
| len = scnprintf(buf, WE_MAX_STR_LEN, "%u ", channel_list.num_channels); |
| if (QDF_STATUS_SUCCESS == sme_get_country_code(mac_handle, ubuf, |
| &ubuf_len)) { |
| /* Printing Country code in getChannelList */ |
| for (i = 0; i < (ubuf_len - 1); i++) |
| len += scnprintf(buf + len, WE_MAX_STR_LEN - len, "%c", ubuf[i]); |
| } |
| for (i = 0; i < channel_list.num_channels; i++) |
| len += scnprintf(buf + len, WE_MAX_STR_LEN - len, " %u", channel_list.channels[i]); |
| |
| wrqu->data.length = strlen(extra) + 1; |
| |
| hdd_exit(); |
| return 0; |
| } |
| |
| static |
| int __iw_get_genie(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_context *hdd_ctx; |
| int ret; |
| QDF_STATUS status; |
| uint32_t length = DOT11F_IE_RSN_MAX_LEN; |
| uint8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN]; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| /* |
| * Actually retrieve the RSN IE from CSR. |
| * (We previously sent it down in the CSR Roam Profile.) |
| */ |
| status = wlan_sap_getstation_ie_information( |
| WLAN_HDD_GET_SAP_CTX_PTR(adapter), |
| &length, genIeBytes); |
| if (status == QDF_STATUS_SUCCESS) { |
| wrqu->data.length = length; |
| if (length > DOT11F_IE_RSN_MAX_LEN) { |
| hdd_err("Invalid buffer length: %d", length); |
| return -E2BIG; |
| } |
| qdf_mem_copy(extra, genIeBytes, length); |
| hdd_debug(" RSN IE of %d bytes returned", |
| wrqu->data.length); |
| } else { |
| wrqu->data.length = 0; |
| hdd_debug(" RSN IE failed to populate"); |
| } |
| |
| hdd_exit(); |
| return 0; |
| } |
| |
| static |
| int iw_get_genie(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_get_genie(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static int |
| __iw_softap_stopbss(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| QDF_STATUS status; |
| struct hdd_context *hdd_ctx; |
| int ret; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { |
| struct hdd_hostapd_state *hostapd_state = |
| WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter); |
| |
| qdf_event_reset(&hostapd_state->qdf_stop_bss_event); |
| status = wlansap_stop_bss( |
| WLAN_HDD_GET_SAP_CTX_PTR(adapter)); |
| if (QDF_IS_STATUS_SUCCESS(status)) { |
| status = |
| qdf_wait_for_event_completion(&hostapd_state-> |
| qdf_stop_bss_event, |
| SME_CMD_STOP_BSS_TIMEOUT); |
| |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| hdd_err("wait for single_event failed!!"); |
| QDF_ASSERT(0); |
| } |
| } |
| clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags); |
| policy_mgr_decr_session_set_pcl(hdd_ctx->psoc, |
| adapter->device_mode, |
| adapter->vdev_id); |
| hdd_green_ap_start_state_mc(hdd_ctx, adapter->device_mode, |
| false); |
| ret = qdf_status_to_os_return(status); |
| } |
| hdd_exit(); |
| return ret; |
| } |
| |
| static int iw_softap_stopbss(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_stopbss(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static int |
| __iw_softap_version(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = netdev_priv(dev); |
| struct hdd_context *hdd_ctx; |
| int ret; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| wrqu->data.length = hdd_wlan_get_version(hdd_ctx, WE_MAX_STR_LEN, |
| extra); |
| hdd_exit(); |
| return 0; |
| } |
| |
| static int iw_softap_version(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_version(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static int hdd_softap_get_sta_info(struct hdd_adapter *adapter, |
| uint8_t *buf, |
| int size) |
| { |
| int i; |
| int written; |
| uint8_t bc_sta_id; |
| |
| hdd_enter(); |
| |
| bc_sta_id = WLAN_HDD_GET_AP_CTX_PTR(adapter)->broadcast_sta_id; |
| |
| written = scnprintf(buf, size, "\nstaId staAddress\n"); |
| for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { |
| struct hdd_station_info *sta = &adapter->sta_info[i]; |
| |
| if (written >= size - 1) |
| break; |
| |
| if (!sta->in_use) |
| continue; |
| |
| if (i == bc_sta_id) |
| continue; |
| |
| written += scnprintf(buf + written, size - written, |
| "%5d "QDF_MAC_ADDR_STR" ecsa=%d\n", |
| sta->sta_id, |
| sta->sta_mac.bytes[0], |
| sta->sta_mac.bytes[1], |
| sta->sta_mac.bytes[2], |
| sta->sta_mac.bytes[3], |
| sta->sta_mac.bytes[4], |
| sta->sta_mac.bytes[5], |
| sta->ecsa_capable); |
| } |
| |
| hdd_exit(); |
| |
| return 0; |
| } |
| |
| static int __iw_softap_get_channel_list(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int ret; |
| struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| struct hdd_context *hdd_ctx; |
| mac_handle_t mac_handle; |
| |
| hdd_enter_dev(dev); |
| |
| if (hdd_validate_adapter(adapter)) { |
| hdd_err_rl("Invalid adapter!!!"); |
| return -ENODEV; |
| } |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| mac_handle = hdd_ctx->mac_handle; |
| |
| ret = iw_get_channel_list_with_cc(dev, mac_handle, |
| info, wrqu, extra); |
| |
| if (0 != ret) |
| return -EINVAL; |
| |
| hdd_exit(); |
| return 0; |
| } |
| |
| static int iw_softap_get_channel_list(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_get_channel_list(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static int __iw_softap_get_sta_info(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct hdd_adapter *adapter; |
| struct hdd_context *hdd_ctx; |
| |
| hdd_enter_dev(dev); |
| |
| adapter = netdev_priv(dev); |
| errno = hdd_validate_adapter(adapter); |
| if (errno) |
| return errno; |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| errno = wlan_hdd_validate_context(hdd_ctx); |
| if (errno) |
| return errno; |
| |
| errno = hdd_check_private_wext_control(hdd_ctx, info); |
| if (errno) |
| return errno; |
| |
| errno = hdd_softap_get_sta_info(adapter, extra, WE_SAP_MAX_STA_INFO); |
| if (errno) { |
| hdd_err("Failed to get sta info; errno:%d", errno); |
| return errno; |
| } |
| |
| wrqu->data.length = strlen(extra); |
| |
| hdd_exit(); |
| |
| return 0; |
| } |
| |
| static int iw_softap_get_sta_info(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_get_sta_info(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static int __iw_softap_get_ba_timeout(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| uint32_t i; |
| enum qca_wlan_ac_type duration[QCA_WLAN_AC_ALL]; |
| void *soc = cds_get_context(QDF_MODULE_ID_SOC); |
| struct hdd_adapter *adapter; |
| struct hdd_context *hdd_ctx; |
| |
| hdd_enter_dev(dev); |
| |
| adapter = netdev_priv(dev); |
| errno = hdd_validate_adapter(adapter); |
| if (errno) |
| return errno; |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| errno = wlan_hdd_validate_context(hdd_ctx); |
| if (errno) |
| return errno; |
| |
| if (!soc) { |
| hdd_err("Invalid handle"); |
| return -EINVAL; |
| } |
| |
| for (i = 0; i < QCA_WLAN_AC_ALL; i++) |
| cdp_get_ba_timeout(soc, i, &duration[i]); |
| |
| snprintf(extra, WE_SAP_MAX_STA_INFO, |
| "\n|------------------------------|\n" |
| "|AC | BA aging timeout duration |\n" |
| "|--------------------------------|\n" |
| "|VO | %d |\n" |
| "|VI | %d |\n" |
| "|BK | %d |\n" |
| "|BE | %d |\n" |
| "|--------------------------------|\n", |
| duration[QCA_WLAN_AC_VO], duration[QCA_WLAN_AC_VI], |
| duration[QCA_WLAN_AC_BK], duration[QCA_WLAN_AC_BE]); |
| |
| wrqu->data.length = strlen(extra) + 1; |
| hdd_exit(); |
| |
| return 0; |
| } |
| |
| static int iw_softap_get_ba_timeout(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_softap_get_ba_timeout(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| static |
| int __iw_get_softap_linkspeed(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| struct hdd_adapter *adapter = (netdev_priv(dev)); |
| struct hdd_context *hdd_ctx; |
| char *out_link_speed = (char *)extra; |
| uint32_t link_speed = 0; |
| int len = sizeof(uint32_t) + 1; |
| struct qdf_mac_addr mac_address; |
| char macaddr_string[MAC_ADDRESS_STR_LEN + 1]; |
| QDF_STATUS status = QDF_STATUS_E_FAILURE; |
| int rc, ret, i; |
| |
| hdd_enter_dev(dev); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hdd_ctx, info); |
| if (0 != ret) |
| return ret; |
| |
| hdd_debug("wrqu->data.length(%d)", wrqu->data.length); |
| |
| /* Linkspeed is allowed only for P2P mode */ |
| if (adapter->device_mode != QDF_P2P_GO_MODE) { |
| hdd_err("Link Speed is not allowed in Device mode %s(%d)", |
| qdf_opmode_str(adapter->device_mode), |
| adapter->device_mode); |
| return -ENOTSUPP; |
| } |
| |
| if (wrqu->data.length >= MAC_ADDRESS_STR_LEN - 1) { |
| if (copy_from_user(macaddr_string, |
| wrqu->data.pointer, MAC_ADDRESS_STR_LEN)) { |
| hdd_err("failed to copy data to user buffer"); |
| return -EFAULT; |
| } |
| macaddr_string[MAC_ADDRESS_STR_LEN - 1] = '\0'; |
| |
| if (!mac_pton(macaddr_string, mac_address.bytes)) { |
| hdd_err("String to Hex conversion Failed"); |
| return -EINVAL; |
| } |
| } |
| /* If no mac address is passed and/or its length is less than 17, |
| * link speed for first connected client will be returned. |
| */ |
| if (wrqu->data.length < 17 || !QDF_IS_STATUS_SUCCESS(status)) { |
| for (i = 0; i < WLAN_MAX_STA_COUNT; i++) { |
| if (adapter->sta_info[i].in_use && |
| (!qdf_is_macaddr_broadcast |
| (&adapter->sta_info[i].sta_mac))) { |
| qdf_copy_macaddr( |
| &mac_address, |
| &adapter->sta_info[i]. |
| sta_mac); |
| status = QDF_STATUS_SUCCESS; |
| break; |
| } |
| } |
| } |
| if (!QDF_IS_STATUS_SUCCESS(status)) { |
| hdd_err("Invalid peer macaddress"); |
| return -EINVAL; |
| } |
| rc = wlan_hdd_get_linkspeed_for_peermac(adapter, &mac_address, |
| &link_speed); |
| if (rc) { |
| hdd_err("Unable to retrieve SME linkspeed"); |
| return rc; |
| } |
| |
| /* linkspeed in units of 500 kbps */ |
| link_speed = link_speed / 500; |
| wrqu->data.length = len; |
| rc = snprintf(out_link_speed, len, "%u", link_speed); |
| if ((rc < 0) || (rc >= len)) { |
| /* encoding or length error? */ |
| hdd_err("Unable to encode link speed"); |
| return -EIO; |
| } |
| hdd_exit(); |
| return 0; |
| } |
| |
| static int |
| iw_get_softap_linkspeed(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_get_softap_linkspeed(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| /** |
| * __iw_get_peer_rssi() - get station's rssi |
| * @dev: net device |
| * @info: iwpriv request information |
| * @wrqu: iwpriv command parameter |
| * @extra |
| * |
| * This function will call wlan_cfg80211_mc_cp_stats_get_peer_rssi |
| * to get rssi |
| * |
| * Return: 0 on success, otherwise error value |
| */ |
| static int |
| __iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret, i; |
| struct hdd_context *hddctx; |
| struct stats_event *rssi_info; |
| char macaddrarray[MAC_ADDRESS_STR_LEN]; |
| struct hdd_adapter *adapter = netdev_priv(dev); |
| struct qdf_mac_addr macaddress = QDF_MAC_ADDR_BCAST_INIT; |
| |
| hdd_enter(); |
| |
| hddctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hddctx); |
| if (ret != 0) |
| return ret; |
| |
| ret = hdd_check_private_wext_control(hddctx, info); |
| if (0 != ret) |
| return ret; |
| |
| hdd_debug("wrqu->data.length= %d", wrqu->data.length); |
| |
| if (wrqu->data.length >= MAC_ADDRESS_STR_LEN - 1) { |
| if (copy_from_user(macaddrarray, |
| wrqu->data.pointer, |
| MAC_ADDRESS_STR_LEN - 1)) { |
| hdd_info("failed to copy data from user buffer"); |
| return -EFAULT; |
| } |
| |
| macaddrarray[MAC_ADDRESS_STR_LEN - 1] = '\0'; |
| hdd_debug("%s", macaddrarray); |
| |
| if (!mac_pton(macaddrarray, macaddress.bytes)) |
| hdd_err("String to Hex conversion Failed"); |
| } |
| |
| rssi_info = wlan_cfg80211_mc_cp_stats_get_peer_rssi(adapter->vdev, |
| macaddress.bytes, |
| &ret); |
| if (ret || !rssi_info) { |
| wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info); |
| return ret; |
| } |
| |
| wrqu->data.length = scnprintf(extra, IW_PRIV_SIZE_MASK, "\n"); |
| for (i = 0; i < rssi_info->num_peer_stats; i++) |
| wrqu->data.length += |
| scnprintf(extra + wrqu->data.length, |
| IW_PRIV_SIZE_MASK - wrqu->data.length, |
| "[%pM] [%d]\n", |
| rssi_info->peer_stats[i].peer_macaddr, |
| rssi_info->peer_stats[i].peer_rssi); |
| |
| wrqu->data.length++; |
| wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info); |
| hdd_exit(); |
| |
| return 0; |
| } |
| |
| /** |
| * iw_get_peer_rssi() - get station's rssi |
| * @dev: net device |
| * @info: iwpriv request information |
| * @wrqu: iwpriv command parameter |
| * @extra |
| * |
| * This function will call __iw_get_peer_rssi |
| * |
| * Return: 0 on success, otherwise error value |
| */ |
| static int |
| iw_get_peer_rssi(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int errno; |
| struct osif_vdev_sync *vdev_sync; |
| |
| errno = osif_vdev_sync_op_start(dev, &vdev_sync); |
| if (errno) |
| return errno; |
| |
| errno = __iw_get_peer_rssi(dev, info, wrqu, extra); |
| |
| osif_vdev_sync_op_stop(vdev_sync); |
| |
| return errno; |
| } |
| |
| /* |
| * Note that the following ioctls were defined with semantics which |
| * cannot be handled by the "iwpriv" userspace application and hence |
| * they are not included in the hostapd_private_args array |
| * QCSAP_IOCTL_ASSOC_STA_MACADDR |
| */ |
| |
| static const struct iw_priv_args hostapd_private_args[] = { |
| { |
| QCSAP_IOCTL_SETPARAM, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam" |
| }, { |
| QCSAP_IOCTL_SETPARAM, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" |
| }, { |
| QCSAP_PARAM_MAX_ASSOC, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, |
| "setMaxAssoc" |
| }, { |
| QCSAP_PARAM_HIDE_SSID, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hideSSID" |
| }, { |
| QCSAP_PARAM_SET_MC_RATE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setMcRate" |
| }, { |
| QCSAP_PARAM_SET_TXRX_FW_STATS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, |
| "txrx_fw_stats" |
| }, { |
| QCSAP_PARAM_SET_TXRX_STATS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, |
| "txrx_stats" |
| }, { |
| QCSAP_PARAM_SET_MCC_CHANNEL_LATENCY, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, |
| "setMccLatency" |
| }, { |
| QCSAP_PARAM_SET_MCC_CHANNEL_QUOTA, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, |
| "setMccQuota" |
| }, { |
| QCSAP_PARAM_SET_CHANNEL_CHANGE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, |
| "setChanChange" |
| }, { |
| QCSAP_PARAM_CONC_SYSTEM_PREF, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, |
| "setConcSysPref" |
| }, |
| #ifdef FEATURE_FW_LOG_PARSING |
| /* Sub-cmds DBGLOG specific commands */ |
| { |
| QCSAP_DBGLOG_LOG_LEVEL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "dl_loglevel" |
| }, { |
| QCSAP_DBGLOG_VAP_ENABLE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dl_vapon" |
| }, { |
| QCSAP_DBGLOG_VAP_DISABLE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "dl_vapoff" |
| }, { |
| QCSAP_DBGLOG_MODULE_ENABLE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dl_modon" |
| }, { |
| QCSAP_DBGLOG_MODULE_DISABLE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "dl_modoff" |
| }, { |
| QCSAP_DBGLOG_MOD_LOG_LEVEL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "dl_mod_loglevel" |
| }, { |
| QCSAP_DBGLOG_TYPE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dl_type" |
| }, { |
| QCSAP_DBGLOG_REPORT_ENABLE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "dl_report" |
| }, |
| #endif /* FEATURE_FW_LOG_PARSING */ |
| { |
| |
| QCASAP_TXRX_FWSTATS_RESET, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "txrx_fw_st_rst" |
| }, { |
| QCSAP_PARAM_RTSCTS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "enablertscts" |
| }, { |
| QCASAP_SET_11N_RATE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set11NRates" |
| }, { |
| QCASAP_SET_VHT_RATE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set11ACRates" |
| }, { |
| QCASAP_SHORT_GI, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "enable_short_gi" |
| }, { |
| QCSAP_SET_AMPDU, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ampdu" |
| }, { |
| QCSAP_SET_AMSDU, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "amsdu" |
| }, { |
| QCSAP_GTX_HT_MCS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "gtxHTMcs" |
| }, { |
| QCSAP_GTX_VHT_MCS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "gtxVHTMcs" |
| }, { |
| QCSAP_GTX_USRCFG, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "gtxUsrCfg" |
| }, { |
| QCSAP_GTX_THRE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "gtxThre" |
| }, { |
| QCSAP_GTX_MARGIN, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "gtxMargin" |
| }, { |
| QCSAP_GTX_STEP, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "gtxStep" |
| }, { |
| QCSAP_GTX_MINTPC, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "gtxMinTpc" |
| }, { |
| QCSAP_GTX_BWMASK, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "gtxBWMask" |
| }, { |
| QCSAP_PARAM_CLR_ACL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setClearAcl" |
| }, { |
| QCSAP_PARAM_ACL_MODE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setAclMode" |
| }, |
| { |
| QCASAP_SET_TM_LEVEL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setTmLevel" |
| }, { |
| QCASAP_SET_DFS_IGNORE_CAC, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setDfsIgnoreCAC" |
| }, { |
| QCASAP_SET_DFS_NOL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setdfsnol" |
| }, { |
| QCASAP_SET_DFS_TARGET_CHNL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setNextChnl" |
| }, { |
| QCASAP_SET_RADAR_CMD, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setRadar" |
| }, |
| { |
| QCSAP_IPA_UC_STAT, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ipaucstat" |
| }, |
| { |
| QCASAP_TX_CHAINMASK_CMD, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_txchainmask" |
| }, { |
| QCASAP_RX_CHAINMASK_CMD, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_rxchainmask" |
| }, { |
| QCASAP_SET_HE_BSS_COLOR, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_he_bss_clr" |
| }, { |
| QCASAP_NSS_CMD, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_nss" |
| }, { |
| QCASAP_SET_PHYMODE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setphymode" |
| }, { |
| QCASAP_DUMP_STATS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "dumpStats" |
| }, { |
| QCASAP_CLEAR_STATS, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "clearStats" |
| }, { |
| QCSAP_START_FW_PROFILING, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "startProfile" |
| }, { |
| QCASAP_PARAM_LDPC, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_ldpc" |
| }, { |
| QCASAP_PARAM_TX_STBC, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_tx_stbc" |
| }, { |
| QCASAP_PARAM_RX_STBC, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_rx_stbc" |
| }, { |
| QCSAP_IOCTL_GETPARAM, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" |
| }, { |
| QCSAP_IOCTL_GETPARAM, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" |
| }, { |
| QCSAP_PARAM_MAX_ASSOC, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getMaxAssoc" |
| }, { |
| QCSAP_PARAM_GET_WLAN_DBG, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwlandbg" |
| }, { |
| QCSAP_GTX_BWMASK, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxBWMask" |
| }, { |
| QCSAP_GTX_MINTPC, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxMinTpc" |
| }, { |
| QCSAP_GTX_STEP, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxStep" |
| }, { |
| QCSAP_GTX_MARGIN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxMargin" |
| }, { |
| QCSAP_GTX_THRE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxThre" |
| }, { |
| QCSAP_GTX_USRCFG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxUsrCfg" |
| }, { |
| QCSAP_GTX_VHT_MCS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxVHTMcs" |
| }, { |
| QCSAP_GTX_HT_MCS, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_gtxHTMcs" |
| }, { |
| QCASAP_SHORT_GI, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_short_gi" |
| }, { |
| QCSAP_PARAM_RTSCTS, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_rtscts" |
| }, { |
| QCASAP_GET_DFS_NOL, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdfsnol" |
| }, { |
| QCSAP_GET_ACL, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_acl_list" |
| }, { |
| QCASAP_PARAM_LDPC, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_ldpc" |
| }, { |
| QCASAP_PARAM_TX_STBC, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_tx_stbc" |
| }, { |
| QCASAP_PARAM_RX_STBC, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_rx_stbc" |
| }, { |
| QCSAP_PARAM_CHAN_WIDTH, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_chwidth" |
| }, { |
| QCASAP_TX_CHAINMASK_CMD, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_txchainmask" |
| }, { |
| QCASAP_RX_CHAINMASK_CMD, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_rxchainmask" |
| }, { |
| QCASAP_NSS_CMD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "get_nss" |
| }, { |
| QCSAP_CAP_TSF, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| "cap_tsf" |
| }, { |
| QCSAP_IOCTL_SET_NONE_GET_THREE, 0, IW_PRIV_TYPE_INT | |
| IW_PRIV_SIZE_FIXED | 3, "" |
| }, { |
| QCSAP_GET_TSF, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, |
| "get_tsf" |
| }, { |
| QCASAP_GET_TEMP_CMD, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_temp" |
| }, { |
| QCSAP_GET_FW_PROFILE_DATA, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getProfileData" |
| }, { |
| QCSAP_IOCTL_GET_STAWPAIE, |
| 0, IW_PRIV_TYPE_BYTE | DOT11F_IE_RSN_MAX_LEN, |
| "get_staWPAIE" |
| }, { |
| QCSAP_IOCTL_STOPBSS, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, |
| "stopbss" |
| }, { |
| QCSAP_IOCTL_VERSION, 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, |
| "version" |
| }, { |
| QCSAP_IOCTL_GET_STA_INFO, 0, |
| IW_PRIV_TYPE_CHAR | WE_SAP_MAX_STA_INFO, "get_sta_info" |
| }, { |
| QCSAP_IOCTL_GET_CHANNEL, 0, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel" |
| }, { |
| QCSAP_IOCTL_GET_BA_AGEING_TIMEOUT, 0, |
| IW_PRIV_TYPE_CHAR | WE_SAP_MAX_STA_INFO, "get_ba_timeout" |
| }, { |
| QCSAP_IOCTL_DISASSOC_STA, |
| IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 6, 0, |
| "disassoc_sta" |
| } |
| /* handler for main ioctl */ |
| , { |
| QCSAP_PRIV_GET_CHAR_SET_NONE, 0, |
| IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "" |
| } |
| /* handler for sub-ioctl */ |
| , { |
| QCSAP_GET_STATS, 0, |
| IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats" |
| } |
| , { |
| QCSAP_LIST_FW_PROFILE, 0, |
| IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "listProfile" |
| } |
| , { |
| QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED, |
| IW_PRIV_TYPE_CHAR | 18, |
| IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" |
| } |
| , { |
| QCSAP_IOCTL_PRIV_GET_RSSI, |
| IW_PRIV_TYPE_CHAR | 18, |
| IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getRSSI" |
| } |
| , { |
| QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" |
| } |
| , |
| /* handlers for sub-ioctl */ |
| { |
| WE_SET_WLAN_DBG, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setwlandbg" |
| } |
| , |
| #ifdef CONFIG_DP_TRACE |
| /* handlers for sub-ioctl */ |
| { |
| WE_SET_DP_TRACE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_dp_trace" |
| } |
| , |
| #endif |
| /* handlers for main ioctl */ |
| { |
| QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE, |
| IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, "" |
| } |
| , { |
| WE_P2P_NOA_CMD, IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, "SetP2pPs" |
| } |
| , { |
| WE_UNIT_TEST_CMD, IW_PRIV_TYPE_INT | MAX_VAR_ARGS, 0, |
| "setUnitTestCmd" |
| } |
| #ifdef WLAN_DEBUG |
| , |
| { |
| WE_SET_CHAN_AVOID, |
| IW_PRIV_TYPE_INT | MAX_VAR_ARGS, |
| 0, |
| "ch_avoid" |
| } |
| #endif |
| , |
| { |
| QCSAP_SET_BTCOEX_MODE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_btc_mode" |
| } |
| , |
| { |
| QCSAP_SET_BTCOEX_LOW_RSSI_THRESHOLD, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_btc_rssi" |
| } |
| , |
| #ifdef FW_THERMAL_THROTTLE_SUPPORT |
| { |
| WE_SET_THERMAL_THROTTLE_CFG, |
| IW_PRIV_TYPE_INT | MAX_VAR_ARGS, |
| 0, "setThermalCfg" |
| } |
| , |
| #endif /* FW_THERMAL_THROTTLE_SUPPORT */ |
| /* handlers for main ioctl */ |
| { |
| QCSAP_IOCTL_MODIFY_ACL, |
| IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 8, 0, "modify_acl" |
| } |
| , |
| /* handlers for main ioctl */ |
| { |
| QCSAP_IOCTL_GET_CHANNEL_LIST, |
| 0, |
| IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, |
| "getChannelList" |
| } |
| , |
| /* handlers for main ioctl */ |
| { |
| QCSAP_IOCTL_SET_TX_POWER, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setTxPower" |
| } |
| , |
| /* handlers for main ioctl */ |
| { |
| QCSAP_IOCTL_SET_MAX_TX_POWER, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setTxMaxPower" |
| } |
| , |
| { |
| QCSAP_IOCTL_SET_PKTLOG, |
| IW_PRIV_TYPE_INT | MAX_VAR_ARGS, |
| 0, "pktlog" |
| } |
| , |
| /* Get HDD CFG Ini param */ |
| { |
| QCSAP_IOCTL_GET_INI_CFG, |
| 0, IW_PRIV_TYPE_CHAR | QCSAP_IOCTL_MAX_STR_LEN, "getConfig" |
| } |
| , |
| /* handlers for main ioctl */ |
| { |
| /* handlers for main ioctl */ |
| QCSAP_IOCTL_SET_TWO_INT_GET_NONE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "" |
| } |
| , |
| /* handlers for sub-ioctl */ |
| #ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT |
| { |
| QCSAP_IOCTL_SET_FW_CRASH_INJECT, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "crash_inject" |
| } |
| , |
| #endif |
| { |
| QCASAP_SET_RADAR_DBG, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "setRadarDbg" |
| } |
| , |
| #ifdef CONFIG_DP_TRACE |
| /* dump dp trace - descriptor or dp trace records */ |
| { |
| QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "dump_dp_trace" |
| } |
| , |
| #endif |
| { |
| QCSAP_ENABLE_FW_PROFILE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "enableProfile" |
| } |
| , |
| { |
| QCSAP_SET_FW_PROFILE_HIST_INTVL, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "set_hist_intvl" |
| } |
| , |
| #ifdef WLAN_SUSPEND_RESUME_TEST |
| { |
| QCSAP_SET_WLAN_SUSPEND, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "wlan_suspend" |
| } |
| , |
| { |
| QCSAP_SET_WLAN_RESUME, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "wlan_resume" |
| } |
| , |
| #endif |
| { |
| QCSAP_SET_BA_AGEING_TIMEOUT, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, |
| 0, "set_ba_timeout" |
| } |
| , |
| { |
| QCASAP_SET_11AX_RATE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_11ax_rate" |
| } |
| , |
| { |
| QCASAP_SET_PEER_RATE, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "set_peer_rate" |
| } |
| , |
| { |
| QCASAP_PARAM_DCM, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "enable_dcm" |
| } |
| , |
| { |
| QCASAP_PARAM_RANGE_EXT, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "range_ext" |
| } |
| , |
| { QCSAP_SET_DEFAULT_AMPDU, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "def_ampdu" |
| } |
| , |
| { QCSAP_ENABLE_RTS_BURSTING, |
| IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
| 0, "rts_bursting" |
| } |
| , |
| }; |
| |
| static const iw_handler hostapd_private[] = { |
| /* set priv ioctl */ |
| [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, |
| /* get priv ioctl */ |
| [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, |
| [QCSAP_IOCTL_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] = |
| iw_softap_get_three, |
| /* get station genIE */ |
| [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, |
| /* stop bss */ |
| [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, |
| /* get driver version */ |
| [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, |
| [QCSAP_IOCTL_GET_CHANNEL - SIOCIWFIRSTPRIV] = |
| iw_softap_getchannel, |
| [QCSAP_IOCTL_ASSOC_STA_MACADDR - SIOCIWFIRSTPRIV] = |
| iw_softap_getassoc_stamacaddr, |
| [QCSAP_IOCTL_DISASSOC_STA - SIOCIWFIRSTPRIV] = |
| iw_softap_disassoc_sta, |
| [QCSAP_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = |
| iw_get_char_setnone, |
| [QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE - |
| SIOCIWFIRSTPRIV] = |
| iw_set_three_ints_getnone, |
| [QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE - |
| SIOCIWFIRSTPRIV] = |
| iw_set_var_ints_getnone, |
| [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV] = |
| iw_softap_modify_acl, |
| [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV] = |
| iw_softap_get_channel_list, |
| [QCSAP_IOCTL_GET_STA_INFO - SIOCIWFIRSTPRIV] = |
| iw_softap_get_sta_info, |
| [QCSAP_IOCTL_GET_BA_AGEING_TIMEOUT - SIOCIWFIRSTPRIV] = |
| iw_softap_get_ba_timeout, |
| [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - |
| SIOCIWFIRSTPRIV] = |
| iw_get_softap_linkspeed, |
| [QCSAP_IOCTL_PRIV_GET_RSSI - SIOCIWFIRSTPRIV] = |
| iw_get_peer_rssi, |
| [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] = |
| iw_softap_set_tx_power, |
| [QCSAP_IOCTL_SET_MAX_TX_POWER - SIOCIWFIRSTPRIV] = |
| iw_softap_set_max_tx_power, |
| [QCSAP_IOCTL_SET_PKTLOG - SIOCIWFIRSTPRIV] = |
| iw_softap_set_pktlog, |
| [QCSAP_IOCTL_GET_INI_CFG - SIOCIWFIRSTPRIV] = |
| iw_softap_get_ini_cfg, |
| [QCSAP_IOCTL_SET_TWO_INT_GET_NONE - SIOCIWFIRSTPRIV] = |
| iw_softap_set_two_ints_getnone, |
| }; |
| |
| const struct iw_handler_def hostapd_handler_def = { |
| .num_standard = 0, |
| .num_private = QDF_ARRAY_SIZE(hostapd_private), |
| .num_private_args = QDF_ARRAY_SIZE(hostapd_private_args), |
| .standard = NULL, |
| .private = (iw_handler *)hostapd_private, |
| .private_args = hostapd_private_args, |
| .get_wireless_stats = NULL, |
| }; |
| |
| /** |
| * hdd_register_wext() - register wext context |
| * @dev: net device handle |
| * |
| * Registers wext interface context for a given net device |
| * |
| * Returns: 0 on success, errno on failure |
| */ |
| void hdd_register_hostapd_wext(struct net_device *dev) |
| { |
| hdd_enter_dev(dev); |
| /* Register as a wireless device */ |
| dev->wireless_handlers = (struct iw_handler_def *)&hostapd_handler_def; |
| |
| hdd_exit(); |
| } |
| |