diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2014-12-11 15:05:01 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2014-12-11 15:05:01 -0800 |
| commit | ac9f925d6b033e37c430b9896569bd3299c2b796 (patch) | |
| tree | 64cfd054689ff703005c24c72d37d27309349076 | |
| parent | a8be39019d38606527fc70c976ec2dd648eb6411 (diff) | |
| parent | 86ec3899544f873b3b18d38c2bd9a0a9a1925ad1 (diff) | |
Merge "Release 1.0.0.254 QCACLD WLAN Driver"
38 files changed, 1473 insertions, 57 deletions
diff --git a/CORE/CLD_TXRX/TLSHIM/tl_shim.c b/CORE/CLD_TXRX/TLSHIM/tl_shim.c index 5da9cba8d39c..b20a57a1057f 100644 --- a/CORE/CLD_TXRX/TLSHIM/tl_shim.c +++ b/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -2524,3 +2524,51 @@ void WLANTL_RegisterOPCbFnc(void *vos_ctx, } #endif /* IPA_UC_OFFLOAD */ +/*============================================================================= + FUNCTION WLANTL_RegisterOCBPeer + + DESCRIPTION + Function to register the OCB Self Peer + + PARAMETERS + IN + vos_ctx : Global OS context context + mac_addr : MAC address of self peer + + OUT + peer_id : Peer ID + + RETURN VALUE + VOS_STATUS_SUCCESS on success + VOS_STATUS_E_FAILURE on failure + + SIDE EFFECTS + +==============================================================================*/ +VOS_STATUS WLANTL_RegisterOCBPeer(void *vos_ctx, uint8_t *mac_addr, + uint8_t *peer_id) +{ + ol_txrx_pdev_handle pdev; + ol_txrx_peer_handle peer; + + pdev = vos_get_context(VOS_MODULE_ID_TXRX, vos_ctx); + if (!pdev) { + TLSHIM_LOGE("%s: Unable to find pdev!", __func__); + return VOS_STATUS_E_FAILURE; + } + + peer = ol_txrx_find_peer_by_addr(pdev, mac_addr, peer_id); + if (!peer) { + TLSHIM_LOGE("%s: Unable to find OCB peer!", __func__); + return VOS_STATUS_E_FAILURE; + } + + ol_txrx_set_ocb_peer(pdev, peer); + + /* Set peer state to connected */ + ol_txrx_peer_state_update(pdev, peer->mac_addr.raw, + ol_txrx_peer_state_auth); + + return VOS_STATUS_SUCCESS; +} + diff --git a/CORE/CLD_TXRX/TXRX/ol_rx.c b/CORE/CLD_TXRX/TXRX/ol_rx.c index fe1fe504dccf..f07e41aa0965 100644 --- a/CORE/CLD_TXRX/TXRX/ol_rx.c +++ b/CORE/CLD_TXRX/TXRX/ol_rx.c @@ -216,6 +216,13 @@ ol_rx_indication_handler( htt_pdev = pdev->htt_pdev; peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (!peer) { + /* If we can't find a peer send this packet to OCB interface using + OCB self peer */ + if (!ol_txrx_get_ocb_peer(pdev, &peer)) + peer = NULL; + } + if (peer) { vdev = peer->vdev; OL_RX_IND_RSSI_UPDATE(peer, rx_ind_msg); diff --git a/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c b/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c index f5da6d44d47e..878dd064b9ed 100644 --- a/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c +++ b/CORE/CLD_TXRX/TXRX/ol_rx_reorder.c @@ -539,6 +539,14 @@ ol_rx_pn_ind_handler( int seq_num, i=0; peer = ol_txrx_peer_find_by_id(pdev, peer_id); + + if (!peer) { + /* If we can't find a peer send this packet to OCB interface using + OCB self peer */ + if (!ol_txrx_get_ocb_peer(pdev, &peer)) + peer = NULL; + } + if (peer) { vdev = peer->vdev; } else { diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_classify.c b/CORE/CLD_TXRX/TXRX/ol_tx_classify.c index 2d8c75249ae5..0c523d90d42b 100644 --- a/CORE/CLD_TXRX/TXRX/ol_tx_classify.c +++ b/CORE/CLD_TXRX/TXRX/ol_tx_classify.c @@ -321,7 +321,8 @@ ol_tx_classify( TX_SCHED_DEBUG_PRINT("Enter %s\n", __func__); dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf); - if (IEEE80211_IS_MULTICAST(dest_addr)) { + if ((IEEE80211_IS_MULTICAST(dest_addr)) + || (vdev->opmode == wlan_op_mode_ocb)) { txq = &vdev->txqs[OL_TX_VDEV_MCAST_BCAST]; tx_msdu_info->htt.info.ext_tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST; if (vdev->opmode == wlan_op_mode_sta) { diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c index 227a40498147..3074edbd9d79 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -2172,6 +2172,45 @@ ol_txrx_ll_set_tx_pause_q_depth( } #endif /* QCA_LL_TX_FLOW_CT */ +/** + * @brief Setter function to store OCB Peer. + */ +void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer) +{ + if (pdev == NULL) { + return; + } + + pdev->ocb_peer = peer; + pdev->ocb_peer_valid = (NULL != peer); +} + +/** + * @brief Getter function to retrieve OCB peer. + * @details + * Returns A_TRUE if ocb_peer is valid + * Otherwise, returns A_FALSE + */ +a_bool_t ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t **peer) +{ + int rc; + + if ((pdev == NULL) || (peer == NULL)) { + rc = A_FALSE; + goto exit; + } + + if (pdev->ocb_peer_valid) { + *peer = pdev->ocb_peer; + rc = A_TRUE; + } else { + rc = A_FALSE; + } + +exit: + return rc; +} + #ifdef IPA_UC_OFFLOAD void ol_txrx_ipa_uc_get_resource( diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h index 94967c62901f..e1362eb04fdb 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx_types.h +++ b/CORE/CLD_TXRX/TXRX/ol_txrx_types.h @@ -714,6 +714,8 @@ struct ol_txrx_pdev_t { void *osif_dev; #endif /* IPA_UC_OFFLOAD */ struct ol_tx_queue_group_t txq_grps[OL_TX_MAX_TXQ_GROUPS]; + u_int8_t ocb_peer_valid; + struct ol_txrx_peer_t *ocb_peer; }; struct ol_txrx_vdev_t { diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h index 0cb804d64cdf..7cf14541f523 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/CORE/HDD/inc/wlan_hdd_cfg.h @@ -2703,6 +2703,17 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */ #define CFG_SAP_AUTH_OFL_KEY_DEFAULT "" #endif /* SAP_AUTH_OFFLOAD */ +enum dot11p_mode { + WLAN_HDD_11P_DISABLED = 0, + WLAN_HDD_11P_STANDALONE, + WLAN_HDD_11P_CONCURRENT, +}; + +#define CFG_DOT11P_MODE_NAME "gDot11PMode" +#define CFG_DOT11P_MODE_DEFAULT ( WLAN_HDD_11P_DISABLED ) +#define CFG_DOT11P_MODE_MIN ( WLAN_HDD_11P_DISABLED ) +#define CFG_DOT11P_MODE_MAX ( WLAN_HDD_11P_CONCURRENT ) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3260,6 +3271,7 @@ typedef struct uint32_t dhcp_client_start_ip; v_U8_t dhcpServerIP[IPADDR_STRING_LENGTH]; #endif /* DHCP_SERVER_OFFLOAD */ + bool enable_mac_spoofing; #ifdef IPA_UC_STA_OFFLOAD bool ipa_uc_sta_offload; @@ -3289,6 +3301,8 @@ typedef struct uint32_t sap_auth_offload_sec_type; uint8_t sap_auth_offload_key[WLAN_PSK_STRING_LENGTH]; #endif /* SAP_AUTH_OFFLOAD */ + + uint8_t dot11p_mode; } hdd_config_t; #ifdef WLAN_FEATURE_MBSSID diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h index 5c9808f8723d..eb7adad18a17 100644 --- a/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -176,6 +176,9 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX = 42, QCA_NL80211_VENDOR_SUBCMD_APFIND = 52, + /* OCB Set Schedule */ + QCA_NL80211_VENDOR_SUBCMD_OCB_SET_SCHED = 53, + QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54, }; @@ -854,6 +857,42 @@ enum qca_wlan_vendor_attr_get_concurrency_matrix { QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_AFTER_LAST - 1, }; +/* OCB Commands */ +enum qca_wlan_vendor_attr_ocb_set_sched +{ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_INVALID = 0, + + /* Number of channels in schedule */ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_NUM_CHANS, + + /* Attribute for nested array of channel attributes */ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN, + + /* Attributes for each channel */ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_IDX, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_FREQ, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_PWR, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_RATE, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_DUR, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_START_GUARD_INT, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_END_GUARD_INT, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_NUM_QOS, + + /* Attribute for nested array of QoS params*/ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM, + + /* Attributes for each QoS Access Category */ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AC, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AIFSN, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMIN, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMAX, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_AFTER_LAST - 1, +}; + /* Feature defines */ #define WIFI_FEATURE_INFRA 0x0001 /* Basic infrastructure mode */ #define WIFI_FEATURE_INFRA_5G 0x0002 /* Support for 5 GHz Band */ diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h index 68ece7964842..955c89abd309 100644 --- a/CORE/HDD/inc/wlan_hdd_main.h +++ b/CORE/HDD/inc/wlan_hdd_main.h @@ -517,7 +517,8 @@ typedef enum device_mode WLAN_HDD_MONITOR, WLAN_HDD_FTM, WLAN_HDD_IBSS, - WLAN_HDD_P2P_DEVICE + WLAN_HDD_P2P_DEVICE, + WLAN_HDD_OCB }device_mode_t; typedef enum rem_on_channel_request_type @@ -1095,6 +1096,9 @@ struct hdd_adapter_s /* variable for temperature in Celsius */ int temperature; + + /* 802.11p */ + struct completion hdd_ocb_set_sched_req_var; }; #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h index ae2a9e8d54cd..7f65dc9851e4 100644 --- a/CORE/HDD/inc/wlan_hdd_tx_rx.h +++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -75,6 +75,10 @@ #define SME_QOS_UAPSD_CFG_VI_CHANGED_MASK 0xF4 #define SME_QOS_UAPSD_CFG_VO_CHANGED_MASK 0xF8 +#define HDD_ETH_HEADER_LEN 14 +#define HDD_OCB_TX_HEADER_LEN 16 +#define HDD_ETHERTYPE_OCB_TX 0x8151 + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 680097c1ef4e..5695fddb43a4 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -3515,6 +3515,13 @@ REG_TABLE_ENTRY g_registry_table[] = VAR_FLAGS_OPTIONAL, (void *) CFG_SAP_AUTH_OFL_KEY_DEFAULT ), #endif /* SAP_AUTH_OFFLOAD */ + + REG_VARIABLE(CFG_DOT11P_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, dot11p_mode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DOT11P_MODE_DEFAULT, + CFG_DOT11P_MODE_MIN, + CFG_DOT11P_MODE_MAX), }; #ifdef WLAN_FEATURE_MBSSID @@ -5960,6 +5967,10 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig->csrConfig.is_sta_connection_in_5gz_enabled = pHddCtx->cfg_ini->is_sta_connection_in_5gz_enabled; + /* Update 802.11p config */ + smeConfig->csrConfig.enable_dot11p = (pHddCtx->cfg_ini->dot11p_mode != + WLAN_HDD_11P_DISABLED); + halStatus = sme_UpdateConfig( pHddCtx->hHal, smeConfig); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c index 16aba7134411..63a35cda5ae9 100644 --- a/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -4622,6 +4622,241 @@ out: } #endif +static const struct +nla_policy +qca_wlan_vendor_ocb_set_sched_policy[ + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX + 1] = +{ + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_NUM_CHANS] = + { .type = NLA_U32 }, + + /* Attributes for each channel */ + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_IDX] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_FREQ] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_PWR] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_RATE] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_DUR] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_START_GUARD_INT] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_END_GUARD_INT] = + { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_NUM_QOS] = + { .type = NLA_U32 }, + + /* Attributes for QoS Params */ + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AC] = + { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AIFSN] = + { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMIN] = + { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMAX] = + { .type = NLA_U8 }, +}; + +static int wlan_hdd_cfg80211_ocb_set_schedule(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX + 1]; + struct nlattr *channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX + 1]; + struct nlattr *qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX + 1]; + struct nlattr *channels; + struct nlattr *qos_params; + int status; + sir_ocb_set_sched_request_t *sched_req = NULL; + sir_ocb_sched_t *sched = NULL; + int rem1, rem2; + int chan_idx; + int ac; + int rc = -EINVAL; + + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + /* Parse the netlink message */ + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX, + data, + data_len, qca_wlan_vendor_ocb_set_sched_policy)) { + hddLog(LOGE, FL("OCB_SET_SCHEDULE_MAX is not present")); + return -EINVAL; + } + + sched_req = vos_mem_malloc(sizeof(*sched_req)); + if (sched_req == NULL) { + hddLog(LOGE, FL("Unable to allocate memory!")); + return -ENOMEM; + + } + vos_mem_set((void *)sched_req, sizeof(*sched_req), 0); + + sched_req->session_id = adapter->sessionId; + sched = &sched_req->sched; + + /* Get the number of channels in schedule */ + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_NUM_CHANS]) { + hddLog(LOGE, FL("NUM_CHANS is not present")); + goto fail; + } + + sched->num_channels = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_NUM_CHANS]); + + /* Get the parameters for each channel in schedule */ + if (!tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN]) { + hddLog(LOGE, FL("CHAN not present")); + goto fail; + } + + nla_for_each_nested(channels, + tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN], + rem1) { + if (nla_parse(channel, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX, + nla_data(channels), nla_len(channels), NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + + /* Parse and fetch parameters for each channel */ + /* Channel index */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_IDX]) { + hddLog(LOGE, FL("CHAN_IDX not present")); + goto fail; + } + chan_idx = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_IDX]); + + /* Channel Number */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_FREQ]) { + hddLog(LOGE, FL("CHAN_FREQ not present")); + goto fail; + } + sched->channels[chan_idx].chan_freq = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_FREQ]); + + /* TX Power */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_PWR]) { + hddLog(LOGE, FL("CHAN_TX_PWR not present")); + goto fail; + } + sched->channels[chan_idx].tx_power = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_PWR]); + + /* TX Rate */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_RATE]) { + hddLog(LOGE, FL("CHAN_TX_RATE not present")); + goto fail; + } + sched->channels[chan_idx].tx_rate = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_TX_RATE]); + + /* Duration */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_DUR]) { + hddLog(LOGE, FL("DUR not present")); + goto fail; + } + sched->channels[chan_idx].duration = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_DUR]); + + /* Start Guard Interval */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_START_GUARD_INT]) { + hddLog(LOGE, FL("START_GUARD_INT not present")); + goto fail; + } + sched->channels[chan_idx].start_guard_interval = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_START_GUARD_INT]); + + /* End Guard Interval */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_END_GUARD_INT]) { + hddLog(LOGE, FL("END_GUARD_INT not present")); + goto fail; + } + sched->channels[chan_idx].end_guard_interval = nla_get_u32( + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_END_GUARD_INT]); + + /* QoS Params */ + if (!channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM]) { + hddLog(LOGE, FL("QOS_PARAM not present")); + goto fail; + } + + nla_for_each_nested(qos_params, + channel[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM], + rem2) { + if (nla_parse(qos_param, + QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_MAX, + nla_data(qos_params), nla_len(qos_params), NULL)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } + + /* Access Category Index */ + if (!qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AC]) { + hddLog(LOGE, FL("QOS_PARAM_AC not present")); + goto fail; + } + ac = nla_get_u8( + qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AC]); + if (ac >= NUM_AC) { + hddLog(LOGE, FL("QOS_PARAM_AIFSN is out of range")); + goto fail; + } + + /* AIFSN */ + if (!qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AIFSN]) { + hddLog(LOGE, FL("QOS_PARAM_AIFSN not present")); + goto fail; + } + sched->channels[chan_idx].qos_params[ac].aifsn = nla_get_u8( + qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_AIFSN]); + + /* CWMIN */ + if (!qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMIN]) { + hddLog(LOGE, FL("QOS_PARAM_CWMIN not present")); + goto fail; + } + sched->channels[chan_idx].qos_params[ac].cwmin = nla_get_u8( + qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMIN]); + + /* CWMAX */ + if (!qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMAX]) { + hddLog(LOGE, FL("QOS_PARAM_CWMAX not present")); + goto fail; + } + sched->channels[chan_idx].qos_params[ac].aifsn = nla_get_u8( + qos_param[QCA_WLAN_VENDOR_ATTR_OCB_SET_SCHED_CHAN_QOS_PARAM_CWMAX]); + } + } + + /* TODO-OCB: Refactor common code path from WEXT and use here */ + + rc = 0; + +fail: + if (sched_req) { + vos_mem_free(sched_req); + } + return rc; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { @@ -4830,6 +5065,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = .doit = (void *)wlan_hdd_cfg80211_do_acs }, #endif + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_SCHED, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = (void *)wlan_hdd_cfg80211_ocb_set_schedule + }, }; diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index 75572214005a..db8ca30f6022 100755 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -8980,6 +8980,7 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, /* fall through */ case WLAN_HDD_P2P_CLIENT: case WLAN_HDD_P2P_DEVICE: + case WLAN_HDD_OCB: { pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name ); @@ -11424,6 +11425,21 @@ VOS_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx) hdd_ctx->reg.cc_src); } +/** + * hdd_set_dot11p_config() - Set 802.11p config flag + * @hdd_ctx: HDD Context pointer + * + * TODO-OCB: This has been temporarily added to ensure this paramter + * is set in CSR when we init the channel list. This should be removed + * once the 5.9 GHz channels are added to the regulatory domain. + */ +void hdd_set_dot11p_config(hdd_context_t *hdd_ctx) +{ + sme_set_dot11p_config(hdd_ctx->hHal, + hdd_ctx->cfg_ini->dot11p_mode != + WLAN_HDD_11P_DISABLED); +} + /**--------------------------------------------------------------------------- \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz @@ -11658,6 +11674,7 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) #endif tANI_U8 rtnl_lock_enable; tANI_U8 reg_netdev_notifier_done = FALSE; + hdd_adapter_t *dot11_adapter = NULL; ENTER(); @@ -11899,6 +11916,13 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) goto err_vosclose; } + /* Set 802.11p config + * TODO-OCB: This has been temporarily added here to ensure this paramter + * is set in CSR when we init the channel list. This should be removed + * once the 5.9 GHz channels are added to the regulatory domain. + */ + hdd_set_dot11p_config(pHddCtx); + if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan) { pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan; @@ -12042,53 +12066,65 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) rtnl_lock_enable = FALSE; #endif - pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d", - wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable ); + if (pHddCtx->cfg_ini->dot11p_mode == WLAN_HDD_11P_STANDALONE) { + /* Create only 802.11p interface */ + pAdapter = hdd_open_adapter(pHddCtx, WLAN_HDD_OCB, + "wlanocb%d", wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable); + } else { + pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d", + wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable ); #ifdef WLAN_OPEN_P2P_INTERFACE - /* Open P2P device interface */ - if (pAdapter != NULL) - { - if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated) - { - vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes, - pHddCtx->cfg_ini->intfMacAddr[0].bytes, - sizeof(tSirMacAddr)); - - /* Generate the P2P Device Address. This consists of the device's - * primary MAC address with the locally administered bit set. - */ - pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02; - } - else - { - tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx); - if (p2p_dev_addr != NULL) - { - vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0], - p2p_dev_addr, VOS_MAC_ADDR_SIZE); + /* Open P2P device interface */ + if (pAdapter != NULL) { + if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated) { + vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes, + pHddCtx->cfg_ini->intfMacAddr[0].bytes, + sizeof(tSirMacAddr)); + + /* Generate the P2P Device Address. This consists of the device's + * primary MAC address with the locally administered bit set. + */ + pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02; + } else { + uint8_t* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx); + if (p2p_dev_addr != NULL) { + vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0], + p2p_dev_addr, VOS_MAC_ADDR_SIZE); + } else { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("Failed to allocate mac_address for p2p_device")); + goto err_close_adapter; + } } - else - { + + pP2pAdapter = hdd_open_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d", + &pHddCtx->p2pDeviceAddress.bytes[0], + rtnl_lock_enable); + + if (NULL == pP2pAdapter) { hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: Failed to allocate mac_address for p2p_device", - __func__); + FL("Failed to do hdd_open_adapter for P2P Device Interface")); goto err_close_adapter; } } - - pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d", - &pHddCtx->p2pDeviceAddress.bytes[0], rtnl_lock_enable ); - - if ( NULL == pP2pAdapter ) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: Failed to do hdd_open_adapter for P2P Device Interface", - __func__); - goto err_close_adapter; +#endif /* WLAN_OPEN_P2P_INTERFACE */ + + /* Open 802.11p Interface */ + if (pAdapter != NULL) { + if (pHddCtx->cfg_ini->dot11p_mode == WLAN_HDD_11P_CONCURRENT) { + dot11_adapter = hdd_open_adapter(pHddCtx, WLAN_HDD_OCB, + "wlanocb%d", wlan_hdd_get_intf_addr(pHddCtx), + rtnl_lock_enable); + + if (dot11_adapter == NULL) { + hddLog(VOS_TRACE_LEVEL_FATAL, + FL("hdd_open_adapter() failed for 802.11p Interface")); + goto err_close_adapter; + } + } } } -#endif if( pAdapter == NULL ) { diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c index a41dc0147bd1..f07843cd8eaf 100644 --- a/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -713,6 +713,40 @@ void hdd_tx_resume_cb(void *adapter_context, } #endif /* QCA_LL_TX_FLOW_CT */ +/** + * hdd_remove_ocb_tx_header() - Function to check for OCB + * TX control header on a packet and extract it if present + * + * @skb: Pointer to OS packet (sk_buff) + */ +static void hdd_remove_ocb_tx_header(struct sk_buff *skb) +{ + struct ethhdr *eth_hdr_p; + struct ethhdr eth_hdr; + + /* Check if TX control header is present */ + eth_hdr_p = (struct ethhdr *) &skb->data[0]; + if (eth_hdr_p->h_proto != htons(HDD_ETHERTYPE_OCB_TX)) { + /* TX control header is not present. Nothing to do.. */ + return; + } + + /* Copy and remove the ethernet header */ + memcpy(ð_hdr, eth_hdr_p, HDD_ETH_HEADER_LEN); + skb_pull(skb, HDD_ETH_HEADER_LEN); + + /* Remove the TX control header */ + skb_pull(skb, HDD_OCB_TX_HEADER_LEN); + + /* Convert Ethernet header to 802.3 header by changing ethertype + field to length field */ + eth_hdr.h_proto = htons(skb->len); + + /* Push the now 802.3 header back */ + skb_push(skb, HDD_ETH_HEADER_LEN); + memcpy(&skb->data[0], ð_hdr, HDD_ETH_HEADER_LEN); +} + /**============================================================================ @brief hdd_hard_start_xmit() - Function registered with the Linux OS for transmitting packets. This version of the function directly passes the packet @@ -776,6 +810,10 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) STAId = pHddStaCtx->conn_info.staId[0]; } + if (pAdapter->device_mode == WLAN_HDD_OCB) { + hdd_remove_ocb_tx_header(skb); + } + #ifdef QCA_LL_TX_FLOW_CT if (VOS_FALSE == WLANTL_GetTxResource((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c index 0e0c0723c16d..5307a165cf5e 100644 --- a/CORE/HDD/src/wlan_hdd_wext.c +++ b/CORE/HDD/src/wlan_hdd_wext.c @@ -433,6 +433,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WLAN_SET_POWER_PARAMS (SIOCIWFIRSTPRIV + 29) +/* 802.11p IOCTL */ +#define WLAN_SET_DOT11P_CHANNEL_SCHED (SIOCIWFIRSTPRIV + 30) + #define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31) /* Private ioctls and their sub-ioctls */ @@ -2997,6 +3000,399 @@ static int iw_get_linkspeed_priv(struct net_device *dev, return 0; } +/* Structure definitions for WLAN_SET_DOT11P_CHANNEL_SCHED */ +#define NUM_AC (4) +#define OCB_CHANNEL_MAX (5) +#define DOT11P_TX_PWR_MAX (23) +#define AIFSN_MIN (2) +#define AIFSN_MAX (15) +#define CW_MIN (1) +#define CW_MAX (10) +#define HDD_OCB_SET_SCHED_TIME_OUT (1500) + +#define NUM_DOT11P_CHANNELS 9 +static const uint32_t valid_dot11p_channels[NUM_DOT11P_CHANNELS] = { + 5860, 5870, 5880, 5890, 5900, 5910, 5920, 5875, 5905, +}; + +/** + * struct ocb_qos_params - QoS Parameters for each AC + * @aifsn: Arbitration Inter-Frame Spacing + * @cwmin: Contention Window (Min) + * @cwmax: Contention Window (Max) + */ +struct ocb_qos_params { + uint8_t aifsn; + uint8_t cwmin; + uint8_t cwmax; +}; + +/** + * struct ocb_channel - Parameters for each OCB channel + * @channel_freq: Channel Frequency (MHz) + * @duration: Channel Duration (ms) + * @start_guard_interval: Start Guard Interval (ms) + * @end_guard_interval: End Guard Interval (ms) + * @tx_power: Transmit Power (dBm) + * @tx_rate: Transmit Data Rate (mbit) + * @qos_params: Array of QoS Parameters + * @per_packet_rx_stats: Enable per packet RX statistics + */ +struct ocb_channel { + uint32_t channel_freq; + uint32_t duration; + uint32_t start_guard_interval; + uint32_t end_guard_interval; + uint32_t tx_power; + uint32_t tx_rate; + struct ocb_qos_params qos_params[NUM_AC]; + uint32_t per_packet_rx_stats; +}; + +/** + * struct dot11p_channel_sched - OCB channel schedule + * @num_channels: Number of channels + * @channels: Array of channel parameters + * @off_channel_tx: Enable off channel TX + */ +struct dot11p_channel_sched { + uint32_t num_channels; + struct ocb_channel channels[OCB_CHANNEL_MAX]; + uint32_t off_channel_tx; +}; + +/** + * dot11p_validate_channel() - Check if specified channel is valid + * @channel: Channel Frequency (MHz) + * + * Return: 0 on success. 1 on failure. + */ +static int dot11p_validate_channel(uint32_t channel) +{ + int i; + + for (i = 0; i < NUM_DOT11P_CHANNELS; i++) { + if (channel == valid_dot11p_channels[i]) { + return 0; + } + } + + return 1; +} + +/** + * dot11p_validate_qos_params() - Check if QoS parameters are valid + * @qos_params: Array of QoS parameters + * + * Return: 0 on success. 1 on failure. + */ +static int dot11p_validate_qos_params(struct ocb_qos_params qos_params[]) +{ + int i; + + for (i = 0; i < NUM_AC; i++) { + if ((!qos_params[i].aifsn) && (!qos_params[i].cwmin) + && (!qos_params[i].cwmax)) { + continue; + } + + /* Validate AIFSN */ + if ((qos_params[i].aifsn < AIFSN_MIN) + || (qos_params[i].aifsn > AIFSN_MAX)) { + return 1; + } + + /* Validate CWMin */ + if ((qos_params[i].cwmin < CW_MIN) + || (qos_params[i].cwmin > CW_MAX)) { + return 1; + } + + /* Validate CWMax */ + if ((qos_params[i].cwmax < CW_MIN) + || (qos_params[i].cwmax > CW_MAX)) { + return 1; + } + } + + return 0; +} + +/** + * dot11p_validate_sched() - Check if schedule is valid + * @sched: OCB channel schedule + * + * Return: 0 on success. 1 on failure. + */ +int dot11p_validate_sched(struct dot11p_channel_sched *sched) +{ + int i; + + if ((sched->num_channels > OCB_CHANNEL_MAX) + || (sched->num_channels == 0)) { + goto error; + } + + for (i = 0; i < sched->num_channels; i++) { + /* Validate channel frequency */ + if (dot11p_validate_channel(sched->channels[i].channel_freq)) { + goto error; + } + + /* Validate TX Power */ + if (sched->channels[i].tx_power > DOT11P_TX_PWR_MAX) { + goto error; + } + + /* Validate TX Rate */ + switch (sched->channels[i].tx_rate) { + case 0: + case 6: + case 9: + case 12: + case 18: + case 24: + case 36: + case 48: + case 54: + break; + default: + goto error; + } + + /* Validate QoS Params */ + if (dot11p_validate_qos_params(sched->channels[i].qos_params)) { + goto error; + } + + if ((sched->channels[i].per_packet_rx_stats != 0) + && (sched->channels[i].per_packet_rx_stats != 1)) { + goto error; + } + } + + return 0; + +error: + return 1; +} + +/** + * hdd_ocb_register_sta() - Register station with Transport Layer + * @adapter: Pointer to HDD Adapter + * + * This function should be invoked in the OCB Set Schedule callback + * to enable the data path in the TL by calling RegisterSTAClient + * + * Return: 0 on success. -1 on failure. + */ +static int hdd_ocb_register_sta(hdd_adapter_t *adapter) +{ + VOS_STATUS vos_status = VOS_STATUS_E_FAILURE; + WLAN_STADescType sta_desc = {0}; + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + u_int8_t peer_id; + v_MACADDR_t wildcardBSSID = { + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }; + + vos_status = WLANTL_RegisterOCBPeer(hdd_ctx->pvosContext, + adapter->macAddressCurrent.bytes, + &peer_id); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("Error registering OCB Self Peer!")); + return -1; + } + + /* Register adapter for STA ID 0 */ + /* TODO-OCB: This is for standalone 802.11p only. We need to change this + * for concurrent mode */ + hdd_ctx->sta_to_adapter[0] = adapter; + + sta_desc.ucSTAId = peer_id; + /* Fill in MAC addresses */ + vos_copy_macaddr(&sta_desc.vSelfMACAddress, &adapter->macAddressCurrent); + vos_copy_macaddr(&sta_desc.vSTAMACAddress, &adapter->macAddressCurrent); + vos_copy_macaddr(&sta_desc.vBSSIDforIBSS, &wildcardBSSID); + + sta_desc.wSTAType = WLAN_STA_OCB; + sta_desc.ucQosEnabled = 1; + sta_desc.ucInitState = WLANTL_STA_AUTHENTICATED; + + vos_status = WLANTL_RegisterSTAClient(hdd_ctx->pvosContext, + hdd_rx_packet_cbk, + hdd_tx_complete_cbk, + hdd_tx_fetch_packet_cbk, &sta_desc, + 0); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) { + hddLog(LOGE, FL("WLANTL_RegisterSTAClient() failed to register. " + "Status= %d [0x%08X]"), vos_status, vos_status); + return -1; + } + + return 0; +} + +/** + * hdd_ocb_set_sched_callback() - OCB Set Schedule callback functions + * @callback_context: Pointer to HDD Adapter + * @rsp: Pointer to response structure + * + * This function is registered as a callback with the lower layers + * and is used to respond with the status of a OCB Set Schedule command. + */ +static void hdd_ocb_set_sched_callback(sir_ocb_set_sched_response_t *resp) +{ + hdd_adapter_t *adapter; + + if (resp == NULL) { + return; + } + + adapter = (hdd_adapter_t *)resp->adapter; + + if (resp->status) { + /* OCB Set Schedule command failed */ + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("OCB set schedule command failed! Status = %d"), + resp->status); + goto exit; + } + + /* OCB Set Schedule command successful. Open TX data path */ + if (hdd_ocb_register_sta(adapter)) { + resp->status = -1; + } else { + netif_carrier_on(adapter->dev); + netif_tx_start_all_queues(adapter->dev); + } + +exit: + complete(&adapter->hdd_ocb_set_sched_req_var); +} + +/** + * iw_set_dot11p_channel_sched() - Handler for WLAN_SET_DOT11P_CHANNEL_SCHED + * ioctl + * @dev: Pointer to net_device structure + * @iw_request_info: IW Request Info + * @wrqu: IW Request Userspace Data Pointer + * @extra: IW Request Kernel Data Pointer + */ +static int iw_set_dot11p_channel_sched(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int rc = 0; + eHalStatus halStatus; + struct dot11p_channel_sched *sched; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + sir_ocb_set_sched_request_t *sched_req = NULL; + sir_ocb_set_sched_response_t *sched_resp = NULL; + sir_ocb_sched_t *sched_ptr; + int i; + + if (wlan_hdd_validate_context(WLAN_HDD_GET_CTX(adapter))) { + hddLog(LOGE, FL("HDD context is not valid")); + return -EINVAL; + } + + if (adapter->device_mode != WLAN_HDD_OCB) { + hddLog(LOGE, FL("Device not in OCB mode!")); + return -EINVAL; + } + + if (extra == NULL) { + hddLog(LOGE, FL("No data in IOCTL!")); + return -EINVAL; + } + + sched = (struct dot11p_channel_sched *)extra; + if (dot11p_validate_sched(sched)) { + hddLog(LOGE, FL("OCB schedule validation failed!")); + return -EINVAL; + } + + /* + * Currently we support only single channel operation. + * Hence, we will only use the first channel in the schedule regardless + * of the number of channels specified. All duration parameters will also + * be ignored. + */ + sched_req = vos_mem_malloc(sizeof(sir_ocb_set_sched_request_t)); + if (sched_req == NULL) { + hddLog(LOGE, FL("Failed to allocate memory!")); + return -ENOMEM; + } + vos_mem_set(sched_req, sizeof(*sched_req), 0); + + sched_resp = vos_mem_malloc(sizeof(sir_ocb_set_sched_response_t)); + if (sched_resp == NULL) { + hddLog(LOGE, FL("Failed to allocate memory!")); + rc = -ENOMEM; + goto exit; + } + vos_mem_set(sched_resp, sizeof(*sched_resp), 0); + + sched_req->session_id = adapter->sessionId; + + sched_ptr = &sched_req->sched; + sched_ptr->num_channels = 1; + sched_ptr->channels[0].chan_freq = sched->channels[0].channel_freq; + sched_ptr->channels[0].tx_power = sched->channels[0].tx_power; + sched_ptr->channels[0].tx_rate = sched->channels[0].tx_rate; + for (i = 0; i < NUM_AC; i++) { + sched_ptr->channels[0].qos_params[i].aifsn = + sched->channels[0].qos_params[i].aifsn; + sched_ptr->channels[0].qos_params[i].cwmin = + sched->channels[0].qos_params[i].cwmin; + sched_ptr->channels[0].qos_params[i].cwmax = + sched->channels[0].qos_params[i].cwmax; + } + sched_ptr->channels[0].rx_stats = sched->channels[0].per_packet_rx_stats; + + sched_resp->adapter = (void *)adapter; + sched_req->resp = sched_resp; + sched_req->callback = hdd_ocb_set_sched_callback; + + netif_tx_disable(adapter->dev); + netif_carrier_off(adapter->dev); + + init_completion(&adapter->hdd_ocb_set_sched_req_var); + halStatus = sme_ocb_set_sched_req(sched_req); + if (halStatus != eHAL_STATUS_SUCCESS) { + rc = -EINVAL; + goto exit; + } + + rc = wait_for_completion_timeout(&adapter->hdd_ocb_set_sched_req_var, + msecs_to_jiffies(HDD_OCB_SET_SCHED_TIME_OUT)); + if (!rc) { + hddLog(LOGE, FL("Timeout waiting for OCB set sched to complete")); + rc = -EINVAL; + goto exit; + } + + /* Check the status code */ + if (sched_resp->status) { + hddLog(LOGE, FL("Error while setting OCB Schedule")); + rc = -EINVAL; + goto exit; + } + + rc = 0; + +exit: + if (sched_req) { + vos_mem_free(sched_req); + } + if (sched_resp) { + vos_mem_free(sched_resp); + } + return rc; +} + + /* * Support for the RSSI & RSSI-APPROX private commands * Per the WiFi framework the response must be of the form @@ -9778,6 +10174,7 @@ static const iw_handler we_private[] = { [WLAN_SET_POWER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_power_params_priv, [WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed_priv, [WLAN_PRIV_SET_TWO_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_two_ints_getnone, + [WLAN_SET_DOT11P_CHANNEL_SCHED - SIOCIWFIRSTPRIV] = iw_set_dot11p_channel_sched, }; /*Maximum command length can be only 15 */ diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h index 0224b806ca3f..cc79bc36282d 100644 --- a/CORE/MAC/inc/aniGlobal.h +++ b/CORE/MAC/inc/aniGlobal.h @@ -1039,10 +1039,14 @@ typedef struct sAniSirGlobal csrReadyToExtWoWCallback readyToExtWoWCallback; void *readyToExtWoWContext; #endif + #ifdef SAP_AUTH_OFFLOAD bool sap_auth_offload; uint32_t sap_auth_offload_sec_type; #endif /* SAP_AUTH_OFFLOAD */ + + /* 802.11p enable */ + bool enable_dot11p; } tAniSirGlobal; typedef enum diff --git a/CORE/MAC/inc/qwlan_version.h b/CORE/MAC/inc/qwlan_version.h index 6125b3662b22..f120a4ee8fa3 100644 --- a/CORE/MAC/inc/qwlan_version.h +++ b/CORE/MAC/inc/qwlan_version.h @@ -42,9 +42,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 0 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 253 +#define QWLAN_VERSION_BUILD 254 -#define QWLAN_VERSIONSTR "1.0.0.253" +#define QWLAN_VERSIONSTR "1.0.0.254" #define AR6320_REV1_VERSION 0x5000000 diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h index b854adabca62..2504e1827f01 100644 --- a/CORE/MAC/inc/sirApi.h +++ b/CORE/MAC/inc/sirApi.h @@ -4285,6 +4285,8 @@ typedef struct sSirUpdateChanParam tANI_U8 chanId; tANI_U8 pwr; tANI_BOOLEAN dfsSet; + bool half_rate; + bool quarter_rate; } tSirUpdateChanParam, *tpSirUpdateChanParam; typedef struct sSirUpdateChan @@ -5615,4 +5617,49 @@ struct tSirSapOffloadInfo }; #endif /* SAP_AUTH_OFFLOAD */ +/* OCB Data Structures and defines */ +#define NUM_AC (4) +#define OCB_CHANNEL_MAX (5) + +typedef struct sir_qos_params { + uint8_t aifsn; + uint8_t cwmin; + uint8_t cwmax; +} sir_qos_params_t; + +typedef struct sir_ocb_channel +{ + uint32_t chan_freq; + uint32_t duration; + uint32_t start_guard_interval; + uint32_t end_guard_interval; + uint32_t tx_power; + uint32_t tx_rate; + sir_qos_params_t qos_params[NUM_AC]; + uint32_t rx_stats; +} sir_ocb_channel_t; + +typedef struct sir_ocb_sched +{ + uint32_t num_channels; + sir_ocb_channel_t channels[OCB_CHANNEL_MAX]; + uint32_t off_channel_tx; +} sir_ocb_sched_t; + +typedef struct sir_ocb_set_sched_response +{ + uint8_t status; + void *adapter; +} sir_ocb_set_sched_response_t; + +typedef void (*ocb_callback_t)(sir_ocb_set_sched_response_t *); + +typedef struct sir_ocb_set_sched_request +{ + uint8_t session_id; + sir_ocb_sched_t sched; + sir_ocb_set_sched_response_t *resp; + ocb_callback_t callback; +} sir_ocb_set_sched_request_t; + #endif /* __SIR_API_H */ diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h index 2985779e5544..37bd57885816 100644 --- a/CORE/MAC/src/include/sirParams.h +++ b/CORE/MAC/src/include/sirParams.h @@ -692,6 +692,8 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_APFIND_SET_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 306) #endif /* WLAN_FEATURE_APFIND */ +#define SIR_HAL_OCB_SET_SCHED_REQUEST (SIR_HAL_ITC_MSG_TYPES_BEGIN + 307) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) // CFG message types diff --git a/CORE/SAP/src/sapChSelect.c b/CORE/SAP/src/sapChSelect.c index 7c3e8b5a0dd2..836ca58ac794 100644 --- a/CORE/SAP/src/sapChSelect.c +++ b/CORE/SAP/src/sapChSelect.c @@ -2351,8 +2351,8 @@ eChannelWidthInfo sapGetChannelWidthInfo(tHalHandle halHandle, ptSapContext pSap else chWidth = CHWIDTH_HT20; } - else if (pSapCtx->csrRoamProfile.phyMode == eSAP_DOT11_MODE_11ac || - pSapCtx->csrRoamProfile.phyMode == eSAP_DOT11_MODE_11ac_ONLY) { + else if (pSapCtx->csrRoamProfile.phyMode == eCSR_CFG_DOT11_MODE_11AC || + pSapCtx->csrRoamProfile.phyMode == eCSR_CFG_DOT11_MODE_11AC_ONLY) { chWidth = CHWIDTH_HT80; } else { diff --git a/CORE/SERVICES/COMMON/dbglog_id.h b/CORE/SERVICES/COMMON/dbglog_id.h index 593c0050e584..672f07ac7ea6 100644 --- a/CORE/SERVICES/COMMON/dbglog_id.h +++ b/CORE/SERVICES/COMMON/dbglog_id.h @@ -928,6 +928,16 @@ extern "C" { #define DATA_TXRX_DBGID_DUP_CHECK 3 #define DATA_TXRX_DBGID_DEFINITION_END 4 +/* HTT module DBGIDs */ +#define HTT_DBGID_DEFINITION_START 0 +#define HTT_DBGID_INVALID_VDEVID_OR_GROUP 1 +#define HTT_DBGID_DISCARD_INTERNAL_PKTS 2 +#define HTT_DBGID_DISCARD_TX_PKTS 3 +#define HTT_DBGID_GROUP_CHANGE 4 +#define HTT_DBGID_GROUP_CREDIT_STATS 5 +#define HTT_DBGID_DISCARD_INTERNAL_PKTS_NUM 6 +#define HTT_DBGID_DEFINITION_END 7 + /* TDLS module DBGIDs*/ #define TDLS_DBGID_DEFINITION_START 0 #define TDLS_DBGID_VDEV_CREATE 1 diff --git a/CORE/SERVICES/COMMON/ol_htt_api.h b/CORE/SERVICES/COMMON/ol_htt_api.h index 3df24b466b39..52de3e4e96ac 100644 --- a/CORE/SERVICES/COMMON/ol_htt_api.h +++ b/CORE/SERVICES/COMMON/ol_htt_api.h @@ -96,8 +96,8 @@ htt_attach_target(htt_pdev_handle htt_pdev); /** * @brief modes that a virtual device can operate as * @details - * A virtual device can operate as an AP, an IBSS, or a STA (client). - * or in monitor mode + * A virtual device can operate as an AP, an IBSS, a STA + * (client), in monitor mode or in OCB mode */ enum htt_op_mode { htt_op_mode_unknown, @@ -105,6 +105,7 @@ enum htt_op_mode { htt_op_mode_ibss, htt_op_mode_sta, htt_op_mode_monitor, + htt_op_mode_ocb, }; /* no-ops */ diff --git a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h index af1904bd3468..9cd5f0ec1fa7 100644 --- a/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h +++ b/CORE/SERVICES/COMMON/ol_txrx_ctrl_api.h @@ -46,8 +46,8 @@ /** * @brief modes that a virtual device can operate as * @details - * A virtual device can operate as an AP, an IBSS, or a STA (client). - * or in monitor mode + * A virtual device can operate as an AP, an IBSS, a STA (client), + * in monitor mode or in OCB mode */ enum wlan_op_mode { wlan_op_mode_unknown, @@ -55,6 +55,7 @@ enum wlan_op_mode { wlan_op_mode_ibss, wlan_op_mode_sta, wlan_op_mode_monitor, + wlan_op_mode_ocb, }; #define OL_TXQ_PAUSE_REASON_FW (1 << 0) @@ -1242,4 +1243,17 @@ void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev); #define ol_txrx_ipa_uc_get_stat(pdev) /* NO-OP */ #endif /* IPA_UC_OFFLOAD */ +/** + * @brief Setter function to store OCB Peer. + */ +void ol_txrx_set_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer); + +/** + * @brief Getter function to retrieve OCB peer. + * @details + * Returns A_TRUE if ocb_peer is valid + * Otherwise, returns A_FALSE + */ +a_bool_t ol_txrx_get_ocb_peer(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t **peer); + #endif /* _OL_TXRX_CTRL_API__H_ */ diff --git a/CORE/SERVICES/COMMON/wdi_in.h b/CORE/SERVICES/COMMON/wdi_in.h index 10fd92cb7144..74c6b2233688 100644 --- a/CORE/SERVICES/COMMON/wdi_in.h +++ b/CORE/SERVICES/COMMON/wdi_in.h @@ -105,8 +105,8 @@ void wdi_in_enable_host_ratectrl(ol_txrx_pdev_handle pdev, u_int32_t enable); /** * @brief modes that a virtual device can operate as * @details - * A virtual device can operate as an AP, an IBSS, or a STA (client). - * or in monitor mode + * A virtual device can operate as an AP, an IBSS, a STA + * (client), in monitor mode or OCB mode */ enum wlan_op_mode { wlan_op_mode_unknown, @@ -114,6 +114,7 @@ enum wlan_op_mode { wlan_op_mode_ibss, wlan_op_mode_sta, wlan_op_mode_monitor, + wlan_op_mode_ocb, }; /** diff --git a/CORE/SERVICES/COMMON/wmi_services.h b/CORE/SERVICES/COMMON/wmi_services.h index 1ed0096c6666..f2eb51df6aad 100644 --- a/CORE/SERVICES/COMMON/wmi_services.h +++ b/CORE/SERVICES/COMMON/wmi_services.h @@ -116,6 +116,7 @@ typedef enum { WMI_SERVICE_MDNS_OFFLOAD, /* mDNS responder offload support */ WMI_SERVICE_SAP_AUTH_OFFLOAD, /* softap auth offload */ WMI_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT, /* Dual Band Simultaneous support */ + WMI_SERVICE_OCB, /* OCB mode support */ WMI_MAX_SERVICE=128 /* max service */ } WMI_SERVICE; diff --git a/CORE/SERVICES/COMMON/wmi_tlv_defs.h b/CORE/SERVICES/COMMON/wmi_tlv_defs.h index 058ee257f24b..cdea12310af1 100644 --- a/CORE/SERVICES/COMMON/wmi_tlv_defs.h +++ b/CORE/SERVICES/COMMON/wmi_tlv_defs.h @@ -527,6 +527,8 @@ typedef enum { WMITLV_TAG_STRUC_wmi_sap_ofl_del_sta_event_fixed_param, WMITLV_TAG_STRUC_wmi_apfind_cmd_param, WMITLV_TAG_STRUC_wmi_apfind_event_hdr, + WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_ocb_set_sched_event_fixed_param, } WMITLV_TAG_ID; /* @@ -726,8 +728,8 @@ typedef enum { OP(WMI_MDNS_GET_STATS_CMDID) \ OP(WMI_SET_ANTENNA_DIVERSITY_CMDID) \ OP(WMI_SAP_OFL_ENABLE_CMDID) \ - OP(WMI_APFIND_CMDID) - + OP(WMI_APFIND_CMDID) \ + OP(WMI_OCB_SET_SCHED_CMDID) /* @@ -822,7 +824,8 @@ typedef enum { OP(WMI_MDNS_STATS_EVENTID) \ OP(WMI_PDEV_RESUME_EVENTID) \ OP(WMI_SAP_OFL_ADD_STA_EVENTID) \ - OP(WMI_SAP_OFL_DEL_STA_EVENTID) + OP(WMI_SAP_OFL_DEL_STA_EVENTID) \ + OP(WMI_OCB_SET_SCHED_EVENTID) /* TLV definitions of WMI commands */ @@ -2025,6 +2028,11 @@ WMITLV_CREATE_PARAM_STRUC(WMI_SAP_OFL_ENABLE_CMDID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, data, WMITLV_SIZE_VAR) WMITLV_CREATE_PARAM_STRUC(WMI_APFIND_CMDID); +/* Set OCB schedule cmd */ +#define WMITLV_TABLE_WMI_OCB_SET_SCHED_CMDID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param, wmi_ocb_set_sched_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_SCHED_CMDID); + /************************** TLV definitions of WMI events *******************************/ /* Service Ready event */ @@ -2507,6 +2515,11 @@ WMITLV_CREATE_PARAM_STRUC(WMI_SAP_OFL_ADD_STA_EVENTID); WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sap_ofl_del_sta_event_fixed_param, wmi_sap_ofl_del_sta_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) WMITLV_CREATE_PARAM_STRUC(WMI_SAP_OFL_DEL_STA_EVENTID); +/* Set OCB schedule event */ +#define WMITLV_TABLE_WMI_OCB_SET_SCHED_EVENTID(id,op,buf,len) \ + WMITLV_ELEM(id, op, buf, len, WMITLV_TAG_STRUC_wmi_ocb_set_sched_event_fixed_param, wmi_ocb_set_sched_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) +WMITLV_CREATE_PARAM_STRUC(WMI_OCB_SET_SCHED_EVENTID); + #ifdef __cplusplus } #endif diff --git a/CORE/SERVICES/COMMON/wmi_unified.h b/CORE/SERVICES/COMMON/wmi_unified.h index 67e639e5eddd..092f6f12eb4b 100644 --- a/CORE/SERVICES/COMMON/wmi_unified.h +++ b/CORE/SERVICES/COMMON/wmi_unified.h @@ -580,6 +580,8 @@ typedef enum { WMI_TPC_CHAINMASK_CONFIG_CMDID, /** set Antenna diversity command */ WMI_SET_ANTENNA_DIVERSITY_CMDID, + /* Set OCB Sched Request */ + WMI_OCB_SET_SCHED_CMDID, /* GPIO Configuration */ WMI_GPIO_CONFIG_CMDID=WMI_CMD_GRP_START_ID(WMI_GRP_GPIO), @@ -918,6 +920,9 @@ typedef enum { WMI_DIAG_EVENTID, + /* Set OCB Sched Response */ + WMI_OCB_SET_SCHED_EVENTID, + /* GPIO Event */ WMI_GPIO_INPUT_EVENTID=WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), /** upload H_CV info WMI event @@ -1030,6 +1035,8 @@ WMI_CHANNEL_CHANGE_CAUSE_CSA, #define WMI_CHAN_FLAG_ALLOW_HT 11 /* HT is allowed on this channel */ #define WMI_CHAN_FLAG_ALLOW_VHT 12 /* VHT is allowed on this channel */ #define WMI_CHANNEL_CHANGE_CAUSE_CSA 13 /*Indicate reason for channel switch */ +#define WMI_CHAN_FLAG_HALF_RATE 14 /* Indicates half rate channel */ +#define WMI_CHAN_FLAG_QUARTER_RATE 15 /* Indicates quarter rate channel */ #define WMI_SET_CHANNEL_FLAG(pwmi_channel,flag) do { \ (pwmi_channel)->info |= (1 << flag); \ @@ -3277,6 +3284,8 @@ typedef struct { **/ #define WMI_VDEV_TYPE_NAN 0x5 +#define WMI_VDEV_TYPE_OCB 0x6 + /** values for vdev_subtype */ #define WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE 0x1 #define WMI_UNIFIED_VDEV_SUBTYPE_P2P_CLIENT 0x2 @@ -9221,6 +9230,61 @@ typedef struct { */ } wmi_apfind_event_hdr; +/** Number of access priorities. */ +#define NUM_AC (4) +/** Max number of channels in the schedule. */ +#define OCB_CHANNEL_MAX (5) + +/* NOTE: Make sure these data structures are identical to those 9235 +* defined in sirApi.h */ + +typedef struct +{ + /** Arbitration Inter-Frame Spacing. Range: 2-15 */ + A_UINT32 aifsn; + /** Contention Window minimum. Range: 1 - 10 */ + A_UINT32 cwmin; + /** Contention Window maximum. Range: 1 - 10 */ + A_UINT32 cwmax; +} wmi_qos_params_t; + +typedef struct +{ + /** Channel frequency in MHz */ + A_UINT32 chan_freq; + /** Channel duration in ms */ + A_UINT32 duration; + /** Start guard interval in ms */ + A_UINT32 start_guard_interval; + /** End guard interval in ms */ + A_UINT32 end_guard_interval; + /** Transmit power in dBm, range 0 - 23 */ + A_UINT32 tx_power; + /** Transmit datarate in Mbps */ + A_UINT32 tx_rate; + /** QoS parameters for each AC */ + wmi_qos_params_t qos_params[NUM_AC]; + /** 1 to enable RX stats for this channel, 0 otherwise */ + A_UINT32 rx_stats; +} wmi_ocb_channel_t; + +typedef struct { + /** TLV tag and len; tag equals + * WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param */ + A_UINT32 tlv_header; + /** Number of valid channels in the channels array */ + A_UINT32 num_channels; + /** The array of channels */ + wmi_ocb_channel_t channels[OCB_CHANNEL_MAX]; + /** 1 to allow off-channel tx, 0 otherwise */ + A_UINT32 off_channel_tx; // Not supported +} wmi_ocb_set_sched_cmd_fixed_param; + +typedef struct { + /** Return status. 0 for success, non-zero otherwise */ + A_UINT32 status; +} wmi_ocb_set_sched_event_fixed_param; + #ifdef __cplusplus } #endif diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 1346618c018e..60cf29b0835b 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -362,6 +362,8 @@ static int wma_roam_event_callback(WMA_HANDLE handle, u_int8_t *event_buf, static VOS_STATUS wma_stop_scan(tp_wma_handle wma_handle, tAbortScanParams *abort_scan_req); +void wma_send_ocb_set_sched_req(void *wma_handle, sir_ocb_sched_t *sched); + static void *wma_find_vdev_by_addr(tp_wma_handle wma, u_int8_t *addr, u_int8_t *vdev_id) { @@ -1018,6 +1020,26 @@ static int wma_vdev_start_rsp_ind(tp_wma_handle wma, u_int8_t *buf) tpAddBssParams bssParams = (tpAddBssParams) req_msg->user_data; vos_mem_copy(iface->bssid, bssParams->bssId, ETH_ALEN); wma_vdev_start_rsp(wma, bssParams, resp_event); + } else if (req_msg->msg_type == WDA_OCB_SET_SCHED_REQUEST) { + sir_ocb_set_sched_response_t *ocb_sched_resp = wma->ocb_resp; + + /* Send VDEV UP command to FW */ + if (wmi_unified_vdev_up_send(wma->wmi_handle, + resp_event->vdev_id, + iface->aid, + iface->bssid) < 0) { + WMA_LOGE("%s : failed to send vdev up", __func__); + return -EEXIST; + } + iface->vdev_up = TRUE; + + /* Invoke the callback function */ + if (ocb_sched_resp) { + ocb_sched_resp->status = 0; + } + if (wma->ocb_callback) { + wma->ocb_callback(ocb_sched_resp); + } } vos_timer_destroy(&req_msg->event_timeout); adf_os_mem_free(req_msg); @@ -5589,6 +5611,9 @@ enum wlan_op_mode wma_get_txrx_vdev_type(u_int32_t type) vdev_type = wlan_op_mode_ibss; break; #endif + case WMI_VDEV_TYPE_OCB: + vdev_type = wlan_op_mode_ocb; + break; case WMI_VDEV_TYPE_MONITOR: default: WMA_LOGE("Invalid vdev type %u", type); @@ -6428,9 +6453,10 @@ static ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, adf_os_atomic_init(&wma_handle->interfaces [self_sta_req->sessionId].bss_status); - if ((self_sta_req->type == WMI_VDEV_TYPE_AP) && + if (((self_sta_req->type == WMI_VDEV_TYPE_AP) && (self_sta_req->subType == - WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) { + WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) + || (self_sta_req->type == WMI_VDEV_TYPE_OCB)) { WMA_LOGA("P2P Device: creating self peer %pM, vdev_id %hu", self_sta_req->selfMacAddr, self_sta_req->sessionId); @@ -7455,6 +7481,12 @@ VOS_STATUS wma_update_channel_list(WMA_HANDLE handle, chan_list->chanParam[i].dfsSet); } + if (chan_list->chanParam[i].half_rate) { + WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_HALF_RATE); + } else if (chan_list->chanParam[i].quarter_rate) { + WMI_SET_CHANNEL_FLAG(chan_info, WMI_CHAN_FLAG_QUARTER_RATE); + } + if (chan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) { WMI_SET_CHANNEL_MODE(chan_info, MODE_11G); } else { @@ -9441,6 +9473,13 @@ static WLAN_PHY_MODE wma_chan_to_mode(u8 chan, ePhyChanBondState chan_offset, break; } } + + /* 5.9 GHz Band */ + if ((chan >= WMA_11P_CHANNEL_BEGIN) && (chan <= WMA_11P_CHANNEL_END)) { + /* Only Legacy Modulation Schemes are supported */ + phymode = MODE_11A; + } + WMA_LOGD("%s: phymode %d channel %d offset %d vht_capable %d " "dot11_mode %d", __func__, phymode, chan, chan_offset, vht_capable, dot11_mode); @@ -9530,6 +9569,14 @@ static VOS_STATUS wma_vdev_start(tp_wma_handle wma, chan->band_center_freq1 -= 10; } chan->band_center_freq2 = 0; + + /* Set half or quarter rate WMI flags */ + if (req->is_half_rate) { + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_HALF_RATE); + } else if (req->is_quarter_rate) { + WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_QUARTER_RATE); + } + /* * If the channel has DFS set, flip on radar reporting. * @@ -9885,6 +9932,27 @@ error0: tgt_req->vdev_id, peer, VOS_FALSE); wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)params, 0); + } else if (tgt_req->msg_type == WDA_OCB_SET_SCHED_REQUEST) { + struct wma_txrx_node *iface; + sir_ocb_set_sched_response_t *ocb_sched_resp = wma->ocb_resp; + + WMA_LOGE("%s: WDA_OCB_SET_SCHED_REQUEST timed out", __func__); + + /* Set vdev_up to FALSE */ + iface = &wma->interfaces[tgt_req->vdev_id]; + iface->vdev_up = FALSE; + + /* Send callback to upper layers with error code */ + if (ocb_sched_resp) { + ocb_sched_resp->status = VOS_STATUS_E_TIMEOUT; + } + /* Call HDD Callback */ + if (wma->ocb_callback) { + wma->ocb_callback(ocb_sched_resp); + } else { + WMA_LOGE("%s: HDD callback is null for OCB Set Schedule\n", + __func__); + } } free_tgt_req: vos_timer_destroy(&tgt_req->event_timeout); @@ -22658,6 +22726,125 @@ static int wma_process_sap_auth_offload(tp_wma_handle wma_handle, } #endif /* SAP_AUTH_OFFLOAD */ +/* TODO-OCB: This function is currently not called. It should be used + * when firmware supports the OCB Set Schedule command + */ +/** + * wma_send_ocb_set_sched_req() - send the OCB schedule to the FW + * + * @wma_handle: context with which the handler is registered. + * @sched: the schedule to be set. + */ +void wma_send_ocb_set_sched_req(void *wma_handle, sir_ocb_sched_t *sched) +{ + int32_t ret; + tp_wma_handle wma = (tp_wma_handle)wma_handle; + wmi_ocb_set_sched_cmd_fixed_param *cmd; + wmi_buf_t buf; + int i; + int j; + + buf = wmi_buf_alloc(wma->wmi_handle, + sizeof(wmi_ocb_set_sched_cmd_fixed_param)); + if (!buf) { + WMA_LOGE("Failed to allocate memory"); + return; + } + + cmd = (wmi_ocb_set_sched_cmd_fixed_param *)wmi_buf_data(buf); + + /* Populate the WMI TLV Header */ + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_ocb_set_sched_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_sched_cmd_fixed_param)); + + /* Populate the WMI command */ + cmd->num_channels = sched->num_channels; + cmd->off_channel_tx = sched->off_channel_tx; + for (i = 0; i < cmd->num_channels; i++) { + cmd->channels[i].chan_freq = sched->channels[i].chan_freq; + cmd->channels[i].duration = sched->channels[i].duration; + cmd->channels[i].start_guard_interval = + sched->channels[i].start_guard_interval; + cmd->channels[i].end_guard_interval = + sched->channels[i].end_guard_interval; + cmd->channels[i].tx_power = sched->channels[i].tx_power; + cmd->channels[i].tx_rate = sched->channels[i].tx_rate; + cmd->channels[i].rx_stats = sched->channels[i].rx_stats; + for (j = 0; j < NUM_AC; j++) { + cmd->channels[i].qos_params[j].aifsn = + sched->channels[i].qos_params[j].aifsn; + cmd->channels[i].qos_params[j].cwmin = + sched->channels[i].qos_params[j].cwmin; + cmd->channels[i].qos_params[j].cwmax = + sched->channels[i].qos_params[j].cwmax; + } + } + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, + sizeof(wmi_ocb_set_sched_cmd_fixed_param), + WMI_OCB_SET_SCHED_CMDID); + if (ret != EOK) { + WMA_LOGE("%s: Failed to send notify cmd ret = %d", __func__, ret); + wmi_buf_free(buf); + } +} + +#define OCB_FREQ_TO_CHAN(x) (((x) - 5000) / 5) + +static void wma_ocb_set_sched_req(void *wma_handle, + sir_ocb_set_sched_request_t *sched_req) +{ + tp_wma_handle wma = (tp_wma_handle)wma_handle; + struct wma_vdev_start_req req; + struct wma_target_req *msg; + VOS_STATUS status = VOS_STATUS_SUCCESS; + sir_ocb_sched_t *sched = &sched_req->sched; + u_int8_t vdev_id; + + WMA_LOGD("%s: Enter", __func__); + + /* Store callback function */ + wma->ocb_callback = sched_req->callback; + wma->ocb_resp = sched_req->resp; + + vos_mem_zero(&req, sizeof(req)); + + vdev_id = sched_req->session_id; + + /* vdev not yet up. Send vdev start request and wait for response. + * OCB Set Schedule request should be sent on receiving + * vdev start response message */ + req.vdev_id = vdev_id; + + /* Enqueue OCB Set Schedule request message */ + msg = wma_fill_vdev_req(wma, req.vdev_id, WDA_OCB_SET_SCHED_REQUEST, + WMA_TARGET_REQ_TYPE_VDEV_START, + (void *)sched_req, 1000); + if (!msg) { + WMA_LOGP("%s: Failed to fill OCB set schedule request for vdev %d", + __func__, req.vdev_id); + status = VOS_STATUS_E_NOMEM; + return; + } + + req.chan = OCB_FREQ_TO_CHAN(sched->channels[0].chan_freq); + req.max_txpow = sched->channels[0].tx_power; + req.is_half_rate = TRUE; + + if (wma->interfaces[vdev_id].vdev_up) { + wma->interfaces[vdev_id].vdev_up = FALSE; + } + + status = wma_vdev_start(wma, &req, VOS_FALSE); + if (status != VOS_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, req.vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + WMA_LOGP("%s: vdev start failed status = %d", __func__, + status); + } +} + /* * function : wma_mc_process_msg * Description : @@ -23298,6 +23485,13 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) vos_mem_free(msg->bodyptr); break; #endif /* WLAN_FEATURE_APFIND */ + + case WDA_OCB_SET_SCHED_REQUEST: + wma_ocb_set_sched_req(wma_handle, + (sir_ocb_set_sched_request_t *)(msg->bodyptr)); + vos_mem_free(msg->bodyptr); + break; + default: WMA_LOGD("unknow msg type %x", msg->type); /* Do Nothing? MSG Body should be freed at here */ @@ -24552,7 +24746,6 @@ static int wma_sap_ofl_add_sta_handler(void *handle, u_int8_t *data, __func__); return 0; } - vos_mem_set(add_sta_req, sizeof(*add_sta_req), 0); add_sta_req->assoc_id = sta_add_event->assoc_id; add_sta_req->conn_req_len = sta_add_event->data_len; @@ -24592,6 +24785,36 @@ static int wma_sap_ofl_del_sta_handler(void *handle, u_int8_t *data, } #endif /* SAP_AUTH_OFFLOAD */ +static int wma_ocb_set_sched_event_handler(void *handle, u_int8_t *event_buf, + u_int32_t len) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + WMI_OCB_SET_SCHED_EVENTID_param_tlvs *param_tlvs; + wmi_ocb_set_sched_event_fixed_param *fix_param; + sir_ocb_set_sched_response_t *ocb_sched_resp = wma->ocb_resp; + + param_tlvs = (WMI_OCB_SET_SCHED_EVENTID_param_tlvs *)event_buf; + fix_param = param_tlvs->fixed_param; + + if (ocb_sched_resp) { + ocb_sched_resp->status = fix_param->status; + } else { + WMA_LOGE("%s: OCB Sched Response is null for OCB Set Schedule\n", + __func__); + return 0; + } + + /* Call HDD Callback */ + if (wma->ocb_callback) { + wma->ocb_callback(ocb_sched_resp); + } else { + WMA_LOGE("%s: HDD callback is null for OCB Set Schedule\n", + __func__); + } + + return 0; +} + /* function : wma_start * Description : * Args : @@ -24768,6 +24991,16 @@ VOS_STATUS wma_start(v_VOID_t *vos_ctx) goto end; } + /* Register event handler for OCB Set Schedule event */ + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_OCB_SET_SCHED_EVENTID, + wma_ocb_set_sched_event_handler); + if (status) { + WMA_LOGE("Failed to register OCB set schedule event cb"); + vos_status = VOS_STATUS_E_FAILURE; + goto end; + } + vos_status = VOS_STATUS_SUCCESS; #ifdef QCA_WIFI_FTM diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 77e2c7e4f9c5..b2473525ad68 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -110,6 +110,9 @@ #define WMA_11G_CHANNEL_BEGIN 1 #define WMA_11G_CHANNEL_END 14 +#define WMA_11P_CHANNEL_BEGIN (172) +#define WMA_11P_CHANNEL_END (184) + #define WMA_LOGD(args...) \ VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, ## args) #define WMA_LOGI(args...) \ @@ -216,6 +219,10 @@ static const t_probeTime_dwellTime #define WMA_EXTSCAN_BURST_DURATION 150 #endif +typedef void (*txFailIndCallback)(u_int8_t *peer_mac, u_int8_t seqNo); + +typedef void (*ocb_set_sched_callback_t)(sir_ocb_set_sched_response_t *resp); + typedef struct { HTC_ENDPOINT_ID endpoint_id; }t_cfg_nv_param; @@ -736,6 +743,10 @@ typedef struct { #ifdef FEATURE_WLAN_D0WOW atomic_t in_d0wow; #endif + + /* OCB Set Schedule Response */ + ocb_set_sched_callback_t ocb_callback; + sir_ocb_set_sched_response_t *ocb_resp; }t_wma_handle, *tp_wma_handle; struct wma_target_cap { @@ -1166,6 +1177,8 @@ struct wma_vdev_start_req { u_int8_t ht_capable; int32_t dfs_pri_multiplier; u_int8_t dot11_mode; + bool is_half_rate; + bool is_quarter_rate; }; struct wma_set_key_params { diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c index aceb34238c2a..5e6da9d45337 100644 --- a/CORE/SERVICES/WMI/wmi_unified.c +++ b/CORE/SERVICES/WMI/wmi_unified.c @@ -604,6 +604,7 @@ static u_int8_t* get_wmi_cmd_string(WMI_CMD_ID wmi_command) CASE_RETURN_STRING(WMI_SET_ANTENNA_DIVERSITY_CMDID); CASE_RETURN_STRING(WMI_SAP_OFL_ENABLE_CMDID); CASE_RETURN_STRING(WMI_APFIND_CMDID); + CASE_RETURN_STRING(WMI_OCB_SET_SCHED_CMDID); } return "Invalid WMI cmd"; } diff --git a/CORE/SME/inc/csrApi.h b/CORE/SME/inc/csrApi.h index e45fff854ca5..f8017dea351e 100644 --- a/CORE/SME/inc/csrApi.h +++ b/CORE/SME/inc/csrApi.h @@ -1238,6 +1238,8 @@ typedef struct tagCsrConfigParam v_U8_t conc_custom_rule1; v_U8_t is_sta_connection_in_5gz_enabled; + /* 802.11p enable */ + bool enable_dot11p; }tCsrConfigParam; //Tush diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h index cfc06565d4f0..4e7240314e1b 100644 --- a/CORE/SME/inc/sme_Api.h +++ b/CORE/SME/inc/sme_Api.h @@ -3832,6 +3832,24 @@ eHalStatus sme_StatsExtRequest(tANI_U8 session_id, tpStatsExtRequestReq input); eHalStatus sme_StatsExtEvent (tHalHandle hHal, void* pMsg); #endif + +/* ------------------------------------------------------------------------- + \fn sme_set_dot11p_config + \brief API to Set 802.11p config + \param hal - The handle returned by macOpen + \param enable_dot11p - 802.11p config param + \return eHalStatus +---------------------------------------------------------------------------*/ +void sme_set_dot11p_config(tHalHandle hal, bool enable_dot11p); + +/* ------------------------------------------------------------------------- + \fn sme_ocb_set_sched_req + \brief API to Indicate OCB Set Schedule Request + \param sched_req - Schedule Request + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_ocb_set_sched_req(sir_ocb_set_sched_request_t *sched_req); + /* --------------------------------------------------------------------------- \fn sme_UpdateDFSScanMode \brief Update DFS roam scan mode diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c index bb990b9807a2..e24e7c811bac 100644 --- a/CORE/SME/src/csr/csrApiRoam.c +++ b/CORE/SME/src/csr/csrApiRoam.c @@ -450,6 +450,7 @@ static tChannelPwrLimit csrFindChannelPwr(tChannelListWithPower * pdefaultPowerT return 0; } +#define NUM_DOT11P_CHANNELS 9 eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) { tSirUpdateChanList *pChanList; @@ -461,6 +462,13 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) tANI_U8 i, j, social_channel[MAX_SOCIAL_CHANNELS] = {1,6,11}; tANI_U8 channel_state; + /* Temporarily add list of 802.11P channels statically */ + /* TODO-OCB: Remove after channels are added to reg domain */ + tANI_U8 dot11p_channels[NUM_DOT11P_CHANNELS] = { + 172, 174, 176, 178, 180, 182, 184, 175, 181, + }; + tANI_U8 dot11p_power = 23; + if (CSR_IS_5G_BAND_ONLY(pMac)) { for (i = 0; i < MAX_SOCIAL_CHANNELS; i++) @@ -471,6 +479,10 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) } } + if (pMac->enable_dot11p) { + numChan += NUM_DOT11P_CHANNELS; + } + bufLen = sizeof(tSirUpdateChanList) + (sizeof(tSirUpdateChanParam) * (numChan)); @@ -482,6 +494,7 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) "Failed to allocate memory for tSirUpdateChanList"); return eHAL_STATUS_FAILED_ALLOC; } + vos_mem_zero(pChanList, bufLen); for (i = 0; i < pScan->base20MHzChannels.numChannels; i++) { @@ -522,6 +535,20 @@ eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac) } } + if (pMac->enable_dot11p) { + /* Add 5.9 GHz channels */ + for (j = 0; j < NUM_DOT11P_CHANNELS; j++) { + pChanList->chanParam[num_channel].chanId = dot11p_channels[j]; + pChanList->chanParam[num_channel].pwr = dot11p_power; + pChanList->chanParam[num_channel].dfsSet = VOS_FALSE; + if ((pChanList->chanParam[num_channel].chanId != 175) + && (pChanList->chanParam[num_channel].chanId != 181)) { + pChanList->chanParam[num_channel].half_rate = VOS_TRUE; + } + num_channel++; + } + } + msg.type = WDA_UPDATE_CHAN_LIST_REQ; msg.reserved = 0; msg.bodyptr = pChanList; @@ -1908,7 +1935,9 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa pMac->roam.configParam.is_sta_connection_in_5gz_enabled = pParam->is_sta_connection_in_5gz_enabled; + pMac->enable_dot11p = pParam->enable_dot11p; } + return status; } @@ -2054,6 +2083,9 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->isRoamOffloadEnabled = pMac->roam.configParam.isRoamOffloadEnabled; #endif + + pParam->enable_dot11p = pMac->enable_dot11p; + csrSetChannels(pMac, pParam); pParam->obssEnabled = pMac->roam.configParam.obssEnabled; diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c index b6edd2e87987..d368ce0c3450 100644 --- a/CORE/SME/src/sme_common/sme_Api.c +++ b/CORE/SME/src/sme_common/sme_Api.c @@ -12295,6 +12295,43 @@ eHalStatus sme_StopBatchScanInd #endif +/* ------------------------------------------------------------------------- + \fn sme_set_dot11p_config + \brief API to Set 802.11p config + \param hal - The handle returned by macOpen + \param enable_dot11p - 802.11p config param + \return eHalStatus +---------------------------------------------------------------------------*/ +void sme_set_dot11p_config(tHalHandle hal, bool enable_dot11p) +{ + tpAniSirGlobal mac = PMAC_STRUCT(hal); + mac->enable_dot11p = enable_dot11p; +} + +/* ------------------------------------------------------------------------- + \fn sme_ocb_set_sched_req + \brief API to Indicate OCB Set Schedule Request + \param sched_req - Schedule Request + \return eHalStatus +---------------------------------------------------------------------------*/ +eHalStatus sme_ocb_set_sched_req(sir_ocb_set_sched_request_t *sched_req) +{ + vos_msg_t msg; + + msg.type = WDA_OCB_SET_SCHED_REQUEST; + msg.reserved = 0; + msg.bodyptr = sched_req; + if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Not able to post WDA_OCB_SET_SCHED_REQUEST message to WDA", + __func__); + return eHAL_STATUS_FAILURE; + } + + return eHAL_STATUS_SUCCESS; +} + void sme_getRecoveryStats(tHalHandle hHal) { tANI_U8 i; diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h index 277d1ae982e5..ef533516ad23 100644 --- a/CORE/TL/inc/wlan_qct_tl.h +++ b/CORE/TL/inc/wlan_qct_tl.h @@ -167,6 +167,8 @@ typedef enum WLAN_STA_TDLS, #endif + WLAN_STA_OCB, + /* Invalid link*/ WLAN_STA_MAX @@ -201,7 +203,6 @@ typedef enum WLANTL_STA_MAX_STATE }WLANTL_STAStateType; - /*--------------------------------------------------------------------------- STA Descriptor Type ---------------------------------------------------------------------------*/ @@ -2936,4 +2937,29 @@ void WLANTL_SetUcActive(void *vos_ctx, void WLANTL_RegisterOPCbFnc(void *vos_ctx, void (*func)(v_U8_t *op_msg, void *usr_ctxt), void *usr_ctxt); #endif /* IPA_UC_OFFLOAD */ + +/*============================================================================= + FUNCTION WLANTL_RegisterOCBPeer + + DESCRIPTION + Function to register the OCB Self Peer + + PARAMETERS + IN + vos_ctx : Global OS context context + mac_addr : MAC address of self peer + + OUT + peer_id : Peer ID + + RETURN VALUE + VOS_STATUS_SUCCESS on success + VOS_STATUS_E_FAILURE on failure + + SIDE EFFECTS + +==============================================================================*/ +VOS_STATUS WLANTL_RegisterOCBPeer(void *vos_ctx, uint8_t *mac_addr, + uint8_t *peer_id); + #endif /* #ifndef WLAN_QCT_WLANTL_H */ diff --git a/CORE/VOSS/inc/vos_types.h b/CORE/VOSS/inc/vos_types.h index 8082bb09b7b8..69f2abe41f61 100644 --- a/CORE/VOSS/inc/vos_types.h +++ b/CORE/VOSS/inc/vos_types.h @@ -146,6 +146,7 @@ typedef enum VOS_FTM_MODE = 5, VOS_IBSS_MODE, VOS_P2P_DEVICE_MODE, + VOS_OCB_MODE, VOS_MAX_NO_OF_MODE } tVOS_CON_MODE; diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index da273fbb80c7..725b0eb28207 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -2337,6 +2337,9 @@ VOS_STATUS vos_get_vdev_types(tVOS_CON_MODE mode, tANI_U32 *type, *type = WMI_VDEV_TYPE_AP; *sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO; break; + case VOS_OCB_MODE: + *type = WMI_VDEV_TYPE_OCB; + break; default: hddLog(VOS_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode); status = VOS_STATUS_E_INVAL; diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h index f07fff3a1201..8a4b7bc0eb7b 100644 --- a/CORE/WDA/inc/wlan_qct_wda.h +++ b/CORE/WDA/inc/wlan_qct_wda.h @@ -1021,6 +1021,8 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_APFIND_SET_CMD SIR_HAL_APFIND_SET_CMD #endif /* WLAN_FEATURE_APFIND */ +#define WDA_OCB_SET_SCHED_REQUEST SIR_HAL_OCB_SET_SCHED_REQUEST + tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg); #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames |
