Exemple #1
0
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;
}
Exemple #2
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;
}