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); }