Esempio n. 1
0
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
			     struct ieee80211_vif *vif, u16 queue,
			     const struct ieee80211_tx_queue_params *params)
{
	struct ath9k_htc_priv *priv = hw->priv;
	struct ath_common *common = ath9k_hw_common(priv->ah);
	struct ath9k_tx_queue_info qi;
	int ret = 0, qnum;

	if (queue >= IEEE80211_NUM_ACS)
		return 0;

	mutex_lock(&priv->mutex);
	ath9k_htc_ps_wakeup(priv);

	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));

	qi.tqi_aifs = params->aifs;
	qi.tqi_cwmin = params->cw_min;
	qi.tqi_cwmax = params->cw_max;
	qi.tqi_burstTime = params->txop * 32;

	qnum = get_hw_qnum(queue, priv->hwq_map);

	ath_dbg(common, CONFIG,
		"Configure tx [queue/hwq] [%d/%d],  aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
		queue, qnum, params->aifs, params->cw_min,
		params->cw_max, params->txop);

	ret = ath_htc_txq_update(priv, qnum, &qi);
	if (ret) {
		ath_err(common, "TXQ Update failed\n");
		goto out;
	}

	if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
	    (qnum == priv->hwq_map[IEEE80211_AC_BE]))
		    ath9k_htc_beaconq_config(priv);
out:
	ath9k_htc_ps_restore(priv);
	mutex_unlock(&priv->mutex);

	return ret;
}
Esempio n. 2
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, hw_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(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);
		hw_qnum = get_hw_qnum(qnum, priv->hwq_map);

		switch (hw_qnum) {
		case 0:
			epid = priv->data_be_ep;
			break;
		case 2:
			epid = priv->data_vi_ep;
			break;
		case 3:
			epid = priv->data_vo_ep;
			break;
		case 1:
		default:
			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);
}