static int ath9k_wmi_cmd_issue(struct wmi *wmi, struct sk_buff *skb, enum wmi_cmd_id cmd, u16 len) { struct wmi_cmd_hdr *hdr; hdr = (struct wmi_cmd_hdr *) skb_push(skb, sizeof(struct wmi_cmd_hdr)); hdr->command_id = cpu_to_be16(cmd); hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); }
void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) { struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl tx_ctl; struct ieee80211_tx_info *info; struct sk_buff *beacon; u8 *tx_fhdr; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); /* FIXME: Handle BMISS */ if (beacon_pending != 0) { priv->bmiss_cnt++; return; } spin_lock_bh(&priv->beacon_lock); if (unlikely(priv->op_flags & OP_SCANNING)) { spin_unlock_bh(&priv->beacon_lock); return; } /* Get a new beacon */ beacon = ieee80211_beacon_get(priv->hw, priv->vif); if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; } info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) beacon->data; priv->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); } tx_ctl.type = ATH9K_HTC_NORMAL; beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); spin_unlock_bh(&priv->beacon_lock); }
static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, int slot) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ieee80211_vif *vif; struct ath9k_htc_vif *avp; struct tx_beacon_header beacon_hdr; struct ath9k_htc_tx_ctl *tx_ctl; struct ieee80211_tx_info *info; struct ieee80211_mgmt *mgmt; struct sk_buff *beacon; u8 *tx_fhdr; int ret; memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); spin_lock_bh(&priv->beacon_lock); vif = priv->cur_beacon_conf.bslot[slot]; avp = (struct ath9k_htc_vif *)vif->drv_priv; if (unlikely(priv->op_flags & OP_SCANNING)) { spin_unlock_bh(&priv->beacon_lock); return; } /* Get a new beacon */ beacon = ieee80211_beacon_get(priv->hw, vif); if (!beacon) { spin_unlock_bh(&priv->beacon_lock); return; } /* * Update the TSF adjust value here, the HW will * add this value for every beacon. */ mgmt = (struct ieee80211_mgmt *)beacon->data; mgmt->u.beacon.timestamp = avp->tsfadjust; info = IEEE80211_SKB_CB(beacon); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) beacon->data; avp->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); } tx_ctl = HTC_SKB_CB(beacon); memset(tx_ctl, 0, sizeof(*tx_ctl)); tx_ctl->type = ATH9K_HTC_BEACON; tx_ctl->epid = priv->beacon_ep; beacon_hdr.vif_index = avp->index; tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); ret = htc_send(priv->htc, beacon); if (ret != 0) { if (ret == -ENOMEM) { ath_dbg(common, BSTUCK, "Failed to send beacon, no free TX buffer\n"); } dev_kfree_skb_any(beacon); } spin_unlock_bh(&priv->beacon_lock); }
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); }