]> Pileus Git - ~andy/linux/blobdiff - drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
ath9k_htc: Move endpoint header parsing to TX tasklet
[~andy/linux] / drivers / net / wireless / ath / ath9k / htc_drv_txrx.c
index d17662fa604a29f4b4e7d5daae7eb91845033e96..7b218dad55d94e74dc8d6cfa2660e66ad8a050e2 100644 (file)
@@ -104,6 +104,30 @@ static enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv,
        return epid;
 }
 
+static inline int strip_drv_header(struct ath9k_htc_priv *priv,
+                                  struct sk_buff *skb)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ath9k_htc_tx_ctl *tx_ctl;
+
+       tx_ctl = HTC_SKB_CB(skb);
+
+       if (tx_ctl->epid == priv->mgmt_ep) {
+               skb_pull(skb, sizeof(struct tx_mgmt_hdr));
+       } else if ((tx_ctl->epid == priv->data_bk_ep) ||
+                  (tx_ctl->epid == priv->data_be_ep) ||
+                  (tx_ctl->epid == priv->data_vi_ep) ||
+                  (tx_ctl->epid == priv->data_vo_ep) ||
+                  (tx_ctl->epid == priv->cab_ep)) {
+               skb_pull(skb, sizeof(struct tx_frame_hdr));
+       } else {
+               ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
                       struct ath9k_tx_queue_info *qinfo)
 {
@@ -281,22 +305,40 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
 void ath9k_tx_tasklet(unsigned long data)
 {
        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_hdr *hdr;
        struct ieee80211_tx_info *tx_info;
        struct sk_buff *skb = NULL;
        __le16 fc;
+       bool txok;
 
        while ((skb = skb_dequeue(&priv->tx.tx_queue)) != NULL) {
 
+               if (strip_drv_header(priv, skb) < 0) {
+                       dev_kfree_skb_any(skb);
+                       continue;
+               }
+
+               tx_ctl = HTC_SKB_CB(skb);
                hdr = (struct ieee80211_hdr *) skb->data;
                fc = hdr->frame_control;
                tx_info = IEEE80211_SKB_CB(skb);
                vif = tx_info->control.vif;
+               txok = tx_ctl->txok;
 
                memset(&tx_info->status, 0, sizeof(tx_info->status));
 
+               /*
+                * URB submission failed for this frame, it never reached
+                * the target.
+                */
+               if (!txok)
+                       goto send_mac80211;
+
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+
                if (!vif)
                        goto send_mac80211;
 
@@ -350,30 +392,10 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
                    enum htc_endpoint_id ep_id, bool txok)
 {
        struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
-       struct ath_common *common = ath9k_hw_common(priv->ah);
-       struct ieee80211_tx_info *tx_info;
-
-       if (!skb)
-               return;
-
-       if (ep_id == priv->mgmt_ep) {
-               skb_pull(skb, sizeof(struct tx_mgmt_hdr));
-       } else if ((ep_id == priv->data_bk_ep) ||
-                  (ep_id == priv->data_be_ep) ||
-                  (ep_id == priv->data_vi_ep) ||
-                  (ep_id == priv->data_vo_ep) ||
-                  (ep_id == priv->cab_ep)) {
-               skb_pull(skb, sizeof(struct tx_frame_hdr));
-       } else {
-               ath_err(common, "Unsupported TX EPID: %d\n", ep_id);
-               dev_kfree_skb_any(skb);
-               return;
-       }
-
-       tx_info = IEEE80211_SKB_CB(skb);
+       struct ath9k_htc_tx_ctl *tx_ctl;
 
-       if (txok)
-               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+       tx_ctl = HTC_SKB_CB(skb);
+       tx_ctl->txok = txok;
 
        skb_queue_tail(&priv->tx.tx_queue, skb);
        tasklet_schedule(&priv->tx_tasklet);