static int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg; u16 action = le16_to_cpu(reg->action); u16 tlv, tlv_buf_len, tlv_buf_left; struct mwifiex_ie_types_header *head; struct ieee80211_regdomain *regd; u8 *tlv_buf; if (action != HostCmd_ACT_GEN_GET) return 0; tlv_buf = (u8 *)reg + sizeof(*reg); tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg); while (tlv_buf_left >= sizeof(*head)) { head = (struct mwifiex_ie_types_header *)tlv_buf; tlv = le16_to_cpu(head->type); tlv_buf_len = le16_to_cpu(head->len); if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) break; switch (tlv) { case TLV_TYPE_CHAN_ATTR_CFG: mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:", (u8 *)head + sizeof(*head), tlv_buf_len); regd = mwifiex_create_custom_regdomain(priv, (u8 *)head + sizeof(*head), tlv_buf_len); if (!IS_ERR(regd)) priv->adapter->regd = regd; break; } tlv_buf += (sizeof(*head) + tlv_buf_len); tlv_buf_left -= (sizeof(*head) + tlv_buf_len); } return 0; }
static int mwifiex_check_ibss_peer_capabilties(struct mwifiex_private *priv, struct mwifiex_sta_node *sta_ptr, struct sk_buff *event) { int evt_len, ele_len; u8 *curr; struct ieee_types_header *ele_hdr; struct mwifiex_ie_types_mgmt_frame *tlv_mgmt_frame; const struct ieee80211_ht_cap *ht_cap; const struct ieee80211_vht_cap *vht_cap; skb_pull(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE); evt_len = event->len; curr = event->data; mwifiex_dbg_dump(priv->adapter, EVT_D, "ibss peer capabilties:", event->data, event->len); skb_push(event, MWIFIEX_IBSS_CONNECT_EVT_FIX_SIZE); tlv_mgmt_frame = (void *)curr; if (evt_len >= sizeof(*tlv_mgmt_frame) && le16_to_cpu(tlv_mgmt_frame->header.type) == TLV_TYPE_UAP_MGMT_FRAME) { /* Locate curr pointer to the start of beacon tlv, * timestamp 8 bytes, beacon intervel 2 bytes, * capability info 2 bytes, totally 12 byte beacon header */ evt_len = le16_to_cpu(tlv_mgmt_frame->header.len); curr += (sizeof(*tlv_mgmt_frame) + 12); } else { mwifiex_dbg(priv->adapter, MSG, "management frame tlv not found!\n"); return 0; } while (evt_len >= sizeof(*ele_hdr)) { ele_hdr = (struct ieee_types_header *)curr; ele_len = ele_hdr->len; if (evt_len < ele_len + sizeof(*ele_hdr)) break; switch (ele_hdr->element_id) { case WLAN_EID_HT_CAPABILITY: sta_ptr->is_11n_enabled = true; ht_cap = (void *)(ele_hdr + 2); sta_ptr->max_amsdu = le16_to_cpu(ht_cap->cap_info) & IEEE80211_HT_CAP_MAX_AMSDU ? MWIFIEX_TX_DATA_BUF_SIZE_8K : MWIFIEX_TX_DATA_BUF_SIZE_4K; mwifiex_dbg(priv->adapter, INFO, "11n enabled!, max_amsdu : %d\n", sta_ptr->max_amsdu); break; case WLAN_EID_VHT_CAPABILITY: sta_ptr->is_11ac_enabled = true; vht_cap = (void *)(ele_hdr + 2); /* check VHT MAXMPDU capability */ switch (le32_to_cpu(vht_cap->vht_cap_info) & 0x3) { case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: sta_ptr->max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_12K; break; case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991: sta_ptr->max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K; break; case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895: sta_ptr->max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K; default: break; } mwifiex_dbg(priv->adapter, INFO, "11ac enabled!, max_amsdu : %d\n", sta_ptr->max_amsdu); break; default: break; } curr += (ele_len + sizeof(*ele_hdr)); evt_len -= (ele_len + sizeof(*ele_hdr)); } return 0; }
static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv, struct sk_buff *event) { int evt_len; u8 *curr; u16 tlv_len; struct mwifiex_ie_types_data *tlv_hdr; struct ieee_types_wmm_parameter *wmm_param_ie = NULL; int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK; priv->wmm_enabled = false; skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE); evt_len = event->len; curr = event->data; mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:", event->data, event->len); while ((evt_len >= sizeof(tlv_hdr->header))) { tlv_hdr = (struct mwifiex_ie_types_data *)curr; tlv_len = le16_to_cpu(tlv_hdr->header.len); if (evt_len < tlv_len + sizeof(tlv_hdr->header)) break; switch (le16_to_cpu(tlv_hdr->header.type)) { case WLAN_EID_HT_CAPABILITY: priv->ap_11n_enabled = true; break; case WLAN_EID_VHT_CAPABILITY: priv->ap_11ac_enabled = true; break; case WLAN_EID_VENDOR_SPECIFIC: /* Point the regular IEEE IE 2 bytes into the Marvell IE * and setup the IEEE IE type and length byte fields */ wmm_param_ie = (void *)(curr + 2); wmm_param_ie->vend_hdr.len = (u8)tlv_len; wmm_param_ie->vend_hdr.element_id = WLAN_EID_VENDOR_SPECIFIC; mwifiex_dbg(priv->adapter, EVENT, "info: check uap capabilities:\t" "wmm parameter set count: %d\n", wmm_param_ie->qos_info_bitmap & mask); mwifiex_wmm_setup_ac_downgrade(priv); priv->wmm_enabled = true; mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); break; default: break; } curr += (tlv_len + sizeof(tlv_hdr->header)); evt_len -= (tlv_len + sizeof(tlv_hdr->header)); } return 0; }