Example #1
0
int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct ieee80211_sta *sta = tx_info->control.sta;
	struct ath9k_htc_sta *ista;
	struct ath9k_htc_tx_ctl tx_ctl;
	enum htc_endpoint_id epid;
	u16 qnum;
	__le16 fc;
	u8 *tx_fhdr;
	u8 sta_idx, vif_idx;

	hdr = (struct ieee80211_hdr *) skb->data;
	fc = hdr->frame_control;

	if (tx_info->control.vif &&
			(struct ath9k_htc_vif *) tx_info->control.vif->drv_priv)
		vif_idx = ((struct ath9k_htc_vif *)
				tx_info->control.vif->drv_priv)->index;
	else
		vif_idx = priv->nvifs;

	if (sta) {
		ista = (struct ath9k_htc_sta *) sta->drv_priv;
		sta_idx = ista->index;
	} else {
		sta_idx = 0;
	}

	memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));

	if (ieee80211_is_data(fc)) {
		struct tx_frame_hdr tx_hdr;
		u8 *qc;

		memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr));

		tx_hdr.node_idx = sta_idx;
		tx_hdr.vif_idx = vif_idx;

		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
			tx_ctl.type = ATH9K_HTC_AMPDU;
			tx_hdr.data_type = ATH9K_HTC_AMPDU;
		} else {
			tx_ctl.type = ATH9K_HTC_NORMAL;
			tx_hdr.data_type = ATH9K_HTC_NORMAL;
		}

		if (ieee80211_is_data_qos(fc)) {
			qc = ieee80211_get_qos_ctl(hdr);
			tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
		}

		/* Check for RTS protection */
		if (priv->hw->wiphy->rts_threshold != (u32) -1)
			if (skb->len > priv->hw->wiphy->rts_threshold)
				tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS;

		/* CTS-to-self */
		if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) &&
		    (priv->op_flags & OP_PROTECT_ENABLE))
			tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY;

		tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
		if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
			tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
		else
			tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx;

		tx_fhdr = skb_push(skb, sizeof(tx_hdr));
		memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));

		qnum = skb_get_queue_mapping(skb);

		switch (qnum) {
		case 0:
			TX_QSTAT_INC(WME_AC_VO);
			epid = priv->data_vo_ep;
			break;
		case 1:
			TX_QSTAT_INC(WME_AC_VI);
			epid = priv->data_vi_ep;
			break;
		case 2:
			TX_QSTAT_INC(WME_AC_BE);
			epid = priv->data_be_ep;
			break;
		case 3:
		default:
			TX_QSTAT_INC(WME_AC_BK);
			epid = priv->data_bk_ep;
			break;
		}
	} else {
		struct tx_mgmt_hdr mgmt_hdr;

		memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));

		tx_ctl.type = ATH9K_HTC_NORMAL;

		mgmt_hdr.node_idx = sta_idx;
		mgmt_hdr.vif_idx = vif_idx;
		mgmt_hdr.tidno = 0;
		mgmt_hdr.flags = 0;

		mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
		if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
			mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
		else
			mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx;

		tx_fhdr = skb_push(skb, sizeof(mgmt_hdr));
		memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr));
		epid = priv->mgmt_ep;
	}

	return htc_send(priv->htc, skb, epid, &tx_ctl);
}
int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct ieee80211_sta *sta = tx_info->control.sta;
	struct ieee80211_vif *vif = tx_info->control.vif;
	struct ath9k_htc_sta *ista;
	struct ath9k_htc_vif *avp;
	struct ath9k_htc_tx_ctl tx_ctl;
	enum htc_endpoint_id epid;
	u16 qnum;
	__le16 fc;
	u8 *tx_fhdr;
	u8 sta_idx, vif_idx;

	hdr = (struct ieee80211_hdr *) skb->data;
	fc = hdr->frame_control;

	/*
	 * Find out on which interface this packet has to be
	 * sent out.
	 */
	if (vif) {
		avp = (struct ath9k_htc_vif *) vif->drv_priv;
		vif_idx = avp->index;
	} else {
		if (!priv->ah->is_monitoring) {
			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
				"VIF is null, but no monitor interface !\n");
			return -EINVAL;
		}

		vif_idx = priv->mon_vif_idx;
	}

	/*
	 * Find out which station this packet is destined for.
	 */
	if (sta) {
		ista = (struct ath9k_htc_sta *) sta->drv_priv;
		sta_idx = ista->index;
	} else {
		sta_idx = priv->vif_sta_pos[vif_idx];
	}

	memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));

	if (ieee80211_is_data(fc)) {
		struct tx_frame_hdr tx_hdr;
		u32 flags = 0;
		u8 *qc;

		memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr));

		tx_hdr.node_idx = sta_idx;
		tx_hdr.vif_idx = vif_idx;

		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
			tx_ctl.type = ATH9K_HTC_AMPDU;
			tx_hdr.data_type = ATH9K_HTC_AMPDU;
		} else {
			tx_ctl.type = ATH9K_HTC_NORMAL;
			tx_hdr.data_type = ATH9K_HTC_NORMAL;
		}

		if (ieee80211_is_data_qos(fc)) {
			qc = ieee80211_get_qos_ctl(hdr);
			tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
		}

		/* Check for RTS protection */
		if (priv->hw->wiphy->rts_threshold != (u32) -1)
			if (skb->len > priv->hw->wiphy->rts_threshold)
				flags |= ATH9K_HTC_TX_RTSCTS;

		/* CTS-to-self */
		if (!(flags & ATH9K_HTC_TX_RTSCTS) &&
		    (vif && vif->bss_conf.use_cts_prot))
			flags |= ATH9K_HTC_TX_CTSONLY;

		tx_hdr.flags = cpu_to_be32(flags);
		tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
		if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
			tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
		else
			tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx;

		tx_fhdr = skb_push(skb, sizeof(tx_hdr));
		memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));

		qnum = skb_get_queue_mapping(skb);

		switch (qnum) {
		case 0:
			TX_QSTAT_INC(WME_AC_VO);
			epid = priv->data_vo_ep;
			break;
		case 1:
			TX_QSTAT_INC(WME_AC_VI);
			epid = priv->data_vi_ep;
			break;
		case 2:
			TX_QSTAT_INC(WME_AC_BE);
			epid = priv->data_be_ep;
			break;
		case 3:
		default:
			TX_QSTAT_INC(WME_AC_BK);
			epid = priv->data_bk_ep;
			break;
		}
	} else {
		struct tx_mgmt_hdr mgmt_hdr;

		memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr));

		tx_ctl.type = ATH9K_HTC_NORMAL;

		mgmt_hdr.node_idx = sta_idx;
		mgmt_hdr.vif_idx = vif_idx;
		mgmt_hdr.tidno = 0;
		mgmt_hdr.flags = 0;

		mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb);
		if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR)
			mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID;
		else
			mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx;

		tx_fhdr = skb_push(skb, sizeof(mgmt_hdr));
		memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr));
		epid = priv->mgmt_ep;
	}

	return htc_send(priv->htc, skb, epid, &tx_ctl);
}