Commit f2820f45 authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville

ath9k_htc: Use helper functions for TX processing

Signed-off-by: default avatarSujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2c5d57f0
...@@ -325,8 +325,8 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, ...@@ -325,8 +325,8 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
return htc_send(priv->htc, skb); return htc_send(priv->htc, skb);
} }
static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
struct ath9k_htc_sta *ista, u8 tid) struct ath9k_htc_sta *ista, u8 tid)
{ {
bool ret = false; bool ret = false;
...@@ -338,89 +338,98 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, ...@@ -338,89 +338,98 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
return ret; return ret;
} }
void ath9k_tx_tasklet(unsigned long data) static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif,
struct sk_buff *skb)
{ {
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
struct ath9k_htc_tx_ctl *tx_ctl;
struct ieee80211_vif *vif;
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *tx_info;
struct sk_buff *skb = NULL;
__le16 fc; __le16 fc;
bool txok;
int slot;
while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) { hdr = (struct ieee80211_hdr *) skb->data;
fc = hdr->frame_control;
slot = strip_drv_header(priv, skb); rcu_read_lock();
if (slot < 0) {
dev_kfree_skb_any(skb);
continue;
}
tx_ctl = HTC_SKB_CB(skb); sta = ieee80211_find_sta(vif, hdr->addr1);
hdr = (struct ieee80211_hdr *) skb->data; if (!sta) {
fc = hdr->frame_control; rcu_read_unlock();
tx_info = IEEE80211_SKB_CB(skb); return;
vif = tx_info->control.vif; }
txok = tx_ctl->txok;
memset(&tx_info->status, 0, sizeof(tx_info->status)); if (sta && conf_is_ht(&priv->hw->conf) &&
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
if (ieee80211_is_data_qos(fc)) {
u8 *qc, tid;
struct ath9k_htc_sta *ista;
/* qc = ieee80211_get_qos_ctl(hdr);
* URB submission failed for this frame, it never reached tid = qc[0] & 0xf;
* the target. ista = (struct ath9k_htc_sta *)sta->drv_priv;
*/ if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) {
if (!txok) ieee80211_start_tx_ba_session(sta, tid, 0);
goto send_mac80211; spin_lock_bh(&priv->tx.tx_lock);
ista->tid_state[tid] = AGGR_PROGRESS;
spin_unlock_bh(&priv->tx.tx_lock);
}
}
}
tx_info->flags |= IEEE80211_TX_STAT_ACK; rcu_read_unlock();
}
if (!vif) static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
goto send_mac80211; struct sk_buff *skb)
{
struct ieee80211_vif *vif;
struct ath9k_htc_tx_ctl *tx_ctl;
struct ieee80211_tx_info *tx_info;
bool txok;
int slot;
rcu_read_lock(); slot = strip_drv_header(priv, skb);
if (slot < 0) {
dev_kfree_skb_any(skb);
return;
}
sta = ieee80211_find_sta(vif, hdr->addr1); tx_ctl = HTC_SKB_CB(skb);
if (!sta) { txok = tx_ctl->txok;
rcu_read_unlock(); tx_info = IEEE80211_SKB_CB(skb);
goto send_mac80211; vif = tx_info->control.vif;
}
/* Check if we need to start aggregation */ memset(&tx_info->status, 0, sizeof(tx_info->status));
if (sta && conf_is_ht(&priv->hw->conf) && /*
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) { * URB submission failed for this frame, it never reached
if (ieee80211_is_data_qos(fc)) { * the target.
u8 *qc, tid; */
struct ath9k_htc_sta *ista; if (!txok || !vif)
goto send_mac80211;
qc = ieee80211_get_qos_ctl(hdr); tx_info->flags |= IEEE80211_TX_STAT_ACK;
tid = qc[0] & 0xf;
ista = (struct ath9k_htc_sta *)sta->drv_priv;
if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { ath9k_htc_check_tx_aggr(priv, vif, skb);
ieee80211_start_tx_ba_session(sta, tid, 0);
spin_lock_bh(&priv->tx.tx_lock);
ista->tid_state[tid] = AGGR_PROGRESS;
spin_unlock_bh(&priv->tx.tx_lock);
}
}
}
rcu_read_unlock(); send_mac80211:
spin_lock_bh(&priv->tx.tx_lock);
if (WARN_ON(--priv->tx.queued_cnt < 0))
priv->tx.queued_cnt = 0;
spin_unlock_bh(&priv->tx.tx_lock);
send_mac80211: ath9k_htc_tx_clear_slot(priv, slot);
spin_lock_bh(&priv->tx.tx_lock);
if (WARN_ON(--priv->tx.queued_cnt < 0)) /* Send status to mac80211 */
priv->tx.queued_cnt = 0; ieee80211_tx_status(priv->hw, skb);
spin_unlock_bh(&priv->tx.tx_lock); }
ath9k_htc_tx_clear_slot(priv, slot); void ath9k_tx_tasklet(unsigned long data)
{
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
struct sk_buff *skb = NULL;
/* Send status to mac80211 */ while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) {
ieee80211_tx_status(priv->hw, skb); ath9k_htc_tx_process(priv, skb);
} }
/* Wake TX queues if needed */ /* Wake TX queues if needed */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment