ath9k: add missing tx locking
[openwrt/svn-archive/archive.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
index ca232a0e530186910c0359657ef09d5df827d681..3312284d1111ed677b38d2d3f4aa0dbe87c173be 100644 (file)
                break;
        case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
        case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
-@@ -3059,10 +3067,16 @@ static int prepare_for_handlers(struct i
+@@ -3008,6 +3016,9 @@ static int prepare_for_handlers(struct i
+       case NL80211_IFTYPE_ADHOC:
+               if (!bssid)
+                       return 0;
++              if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
++                  ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
++                      return 0;
+               if (ieee80211_is_beacon(hdr->frame_control)) {
+                       return 1;
+               } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
+@@ -3059,10 +3070,16 @@ static int prepare_for_handlers(struct i
                }
                break;
        case NL80211_IFTYPE_WDS:
  }
  
  static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
-@@ -380,7 +456,6 @@ static void ath_tx_complete_aggr(struct 
+@@ -323,6 +399,7 @@ static struct ath_buf* ath_clone_txbuf(s
+       tbf->bf_buf_addr = bf->bf_buf_addr;
+       memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
+       tbf->bf_state = bf->bf_state;
++      tbf->bf_state.stale = false;
+       return tbf;
+ }
+@@ -380,7 +457,6 @@ static void ath_tx_complete_aggr(struct 
        struct ieee80211_tx_rate rates[4];
        struct ath_frame_info *fi;
        int nframes;
        bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
        int i, retries;
        int bar_index = -1;
-@@ -406,7 +481,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -406,7 +482,7 @@ static void ath_tx_complete_aggr(struct 
                while (bf) {
                        bf_next = bf->bf_next;
  
                                list_move_tail(&bf->list, &bf_head);
  
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
-@@ -417,8 +492,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -417,8 +493,7 @@ static void ath_tx_complete_aggr(struct 
        }
  
        an = (struct ath_node *)sta->drv_priv;
        seq_first = tid->seq_start;
        isba = ts->ts_flags & ATH9K_TX_BA;
  
-@@ -430,7 +504,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -430,7 +505,7 @@ static void ath_tx_complete_aggr(struct 
         * Only BlockAcks have a TID and therefore normal Acks cannot be
         * checked
         */
                txok = false;
  
        isaggr = bf_isaggr(bf);
-@@ -466,7 +540,8 @@ static void ath_tx_complete_aggr(struct 
+@@ -466,7 +541,8 @@ static void ath_tx_complete_aggr(struct 
                tx_info = IEEE80211_SKB_CB(skb);
                fi = get_frame_info(skb);
  
                        /*
                         * Outside of the current BlockAck window,
                         * maybe part of a previous session
-@@ -499,7 +574,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -499,7 +575,7 @@ static void ath_tx_complete_aggr(struct 
                 * not a holding desc.
                 */
                INIT_LIST_HEAD(&bf_head);
                        list_move_tail(&bf->list, &bf_head);
  
                if (!txpending) {
-@@ -523,7 +598,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -523,7 +599,7 @@ static void ath_tx_complete_aggr(struct 
                                ieee80211_sta_eosp(sta);
                        }
                        /* retry the un-acked ones */
                                struct ath_buf *tbf;
  
                                tbf = ath_clone_txbuf(sc, bf_last);
-@@ -560,7 +635,7 @@ static void ath_tx_complete_aggr(struct 
+@@ -560,7 +636,7 @@ static void ath_tx_complete_aggr(struct 
                if (an->sleeping)
                        ieee80211_sta_set_buffered(sta, tid->tidno, true);
  
                if (!an->sleeping) {
                        ath_tx_queue_tid(txq, tid);
  
-@@ -618,7 +693,7 @@ static void ath_tx_process_buffer(struct
+@@ -618,7 +694,7 @@ static void ath_tx_process_buffer(struct
        } else
                ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok);
  
                ath_txq_schedule(sc, txq);
  }
  
-@@ -792,15 +867,20 @@ static int ath_compute_num_delims(struct
+@@ -792,15 +868,20 @@ static int ath_compute_num_delims(struct
  
  static struct ath_buf *
  ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
                if (!skb)
                        break;
  
-@@ -808,13 +888,26 @@ ath_tx_get_tid_subframe(struct ath_softc
+@@ -808,13 +889,26 @@ ath_tx_get_tid_subframe(struct ath_softc
                bf = fi->bf;
                if (!fi->bf)
                        bf = ath_tx_setup_buffer(sc, txq, tid, skb);
                bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
                seqno = bf->bf_state.seqno;
  
-@@ -828,73 +921,52 @@ ath_tx_get_tid_subframe(struct ath_softc
+@@ -828,73 +922,52 @@ ath_tx_get_tid_subframe(struct ath_softc
  
                        INIT_LIST_HEAD(&bf_head);
                        list_add(&bf->list, &bf_head);
                }
  
                /* add padding for previous frame to aggregation length */
-@@ -912,22 +984,37 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+@@ -912,22 +985,37 @@ static enum ATH_AGGR_STATUS ath_tx_form_
                bf->bf_next = NULL;
  
                /* link buffers of this frame to the aggregate */
  #undef PADBYTES
  }
  
-@@ -999,7 +1086,7 @@ void ath_update_max_aggr_framelen(struct
+@@ -999,7 +1087,7 @@ void ath_update_max_aggr_framelen(struct
  }
  
  static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
  {
        struct ath_hw *ah = sc->sc_ah;
        struct sk_buff *skb;
-@@ -1008,6 +1095,7 @@ static void ath_buf_set_rate(struct ath_
+@@ -1008,6 +1096,7 @@ static void ath_buf_set_rate(struct ath_
        const struct ieee80211_rate *rate;
        struct ieee80211_hdr *hdr;
        struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
        int i;
        u8 rix = 0;
  
-@@ -1030,7 +1118,17 @@ static void ath_buf_set_rate(struct ath_
+@@ -1030,7 +1119,17 @@ static void ath_buf_set_rate(struct ath_
                rix = rates[i].idx;
                info->rates[i].Tries = rates[i].count;
  
                        info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
                        info->flags |= ATH9K_TXDESC_RTSENA;
                } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-@@ -1123,6 +1221,8 @@ static void ath_tx_fill_desc(struct ath_
+@@ -1123,6 +1222,8 @@ static void ath_tx_fill_desc(struct ath_
        struct ath_hw *ah = sc->sc_ah;
        struct ath_buf *bf_first = NULL;
        struct ath_tx_info info;
  
        memset(&info, 0, sizeof(info));
        info.is_first = true;
-@@ -1159,7 +1259,22 @@ static void ath_tx_fill_desc(struct ath_
+@@ -1159,7 +1260,22 @@ static void ath_tx_fill_desc(struct ath_
                                info.flags |= (u32) bf->bf_state.bfs_paprd <<
                                              ATH9K_TXDESC_PAPRD_S;
  
                }
  
                info.buf_addr[0] = bf->bf_buf_addr;
-@@ -1188,53 +1303,86 @@ static void ath_tx_fill_desc(struct ath_
+@@ -1188,64 +1304,101 @@ static void ath_tx_fill_desc(struct ath_
        }
  }
  
 +              *stop = true;
 +              return false;
 +      }
--              ath_tx_fill_desc(sc, bf, txq, aggr_len);
--              ath_tx_txqaddbuf(sc, txq, &bf_q, false);
--      } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
--               status != ATH_AGGR_BAW_CLOSED);
++
 +      ath_set_rates(tid->an->vif, tid->an->sta, bf);
 +      if (aggr)
 +              last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
 +              tid->ac->clear_ps_filter = false;
 +              tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
 +      }
-+
+-              ath_tx_fill_desc(sc, bf, txq, aggr_len);
+-              ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+-      } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
+-               status != ATH_AGGR_BAW_CLOSED);
 +      ath_tx_fill_desc(sc, bf, txq, aggr_len);
 +      ath_tx_txqaddbuf(sc, txq, &bf_q, false);
 +      return true;
  }
  
  int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
-@@ -1258,6 +1406,9 @@ int ath_tx_aggr_start(struct ath_softc *
+                     u16 tid, u16 *ssn)
+ {
+       struct ath_atx_tid *txtid;
++      struct ath_txq *txq;
+       struct ath_node *an;
+       u8 density;
+       an = (struct ath_node *)sta->drv_priv;
+       txtid = ATH_AN_2_TID(an, tid);
++      txq = txtid->ac->txq;
++
++      ath_txq_lock(sc, txq);
+       /* update ampdu factor/density, they may have changed. This may happen
+        * in HT IBSS when a beacon with HT-info is received after the station
+@@ -1258,6 +1411,9 @@ int ath_tx_aggr_start(struct ath_softc *
                an->mpdudensity = density;
        }
  
        txtid->active = true;
        txtid->paused = true;
        *ssn = txtid->seq_start = txtid->seq_next;
-@@ -1277,8 +1428,9 @@ void ath_tx_aggr_stop(struct ath_softc *
+@@ -1266,6 +1422,8 @@ int ath_tx_aggr_start(struct ath_softc *
+       memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
+       txtid->baw_head = txtid->baw_tail = 0;
++      ath_txq_unlock_complete(sc, txq);
++
+       return 0;
+ }
+@@ -1277,8 +1435,9 @@ void ath_tx_aggr_stop(struct ath_softc *
  
        ath_txq_lock(sc, txq);
        txtid->active = false;
        ath_txq_unlock_complete(sc, txq);
  }
  
-@@ -1302,7 +1454,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
+@@ -1302,7 +1461,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
  
                ath_txq_lock(sc, txq);
  
  
                tid->sched = false;
                list_del(&tid->list);
-@@ -1334,7 +1486,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
+@@ -1334,7 +1493,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
                ath_txq_lock(sc, txq);
                ac->clear_ps_filter = true;
  
                        ath_tx_queue_tid(txq, tid);
                        ath_txq_schedule(sc, txq);
                }
-@@ -1359,7 +1511,7 @@ void ath_tx_aggr_resume(struct ath_softc
+@@ -1359,7 +1518,7 @@ void ath_tx_aggr_resume(struct ath_softc
        tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
        tid->paused = false;
  
                ath_tx_queue_tid(txq, tid);
                ath_txq_schedule(sc, txq);
        }
-@@ -1379,6 +1531,7 @@ void ath9k_release_buffered_frames(struc
+@@ -1379,6 +1538,7 @@ void ath9k_release_buffered_frames(struc
        struct ieee80211_tx_info *info;
        struct list_head bf_q;
        struct ath_buf *bf_tail = NULL, *bf;
        int sent = 0;
        int i;
  
-@@ -1394,15 +1547,15 @@ void ath9k_release_buffered_frames(struc
+@@ -1394,16 +1554,18 @@ void ath9k_release_buffered_frames(struc
                        continue;
  
                ath_txq_lock(sc, tid->ac->txq);
                        list_add_tail(&bf->list, &bf_q);
                        ath_set_rates(tid->an->vif, tid->an->sta, bf);
 -                      ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
-+                      ath_tx_addto_baw(sc, tid, bf);
-                       bf->bf_state.bf_type &= ~BUF_AGGR;
+-                      bf->bf_state.bf_type &= ~BUF_AGGR;
++                      if (bf_isampdu(bf)) {
++                              ath_tx_addto_baw(sc, tid, bf);
++                              bf->bf_state.bf_type &= ~BUF_AGGR;
++                      }
                        if (bf_tail)
                                bf_tail->bf_next = bf;
-@@ -1412,7 +1565,7 @@ void ath9k_release_buffered_frames(struc
+@@ -1412,7 +1574,7 @@ void ath9k_release_buffered_frames(struc
                        sent++;
                        TX_STAT_INC(txq->axq_qnum, a_queued_hw);
  
                                ieee80211_sta_set_buffered(an->sta, i, false);
                }
                ath_txq_unlock_complete(sc, tid->ac->txq);
-@@ -1571,7 +1724,7 @@ static void ath_drain_txq_list(struct at
+@@ -1571,7 +1733,7 @@ static void ath_drain_txq_list(struct at
        while (!list_empty(list)) {
                bf = list_first_entry(list, struct ath_buf, list);
  
                        list_del(&bf->list);
  
                        ath_tx_return_buffer(sc, bf);
-@@ -1665,25 +1818,27 @@ void ath_tx_cleanupq(struct ath_softc *s
+@@ -1665,25 +1827,27 @@ void ath_tx_cleanupq(struct ath_softc *s
   */
  void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
  {
                        tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
                                               list);
                        list_del(&tid->list);
-@@ -1692,17 +1847,17 @@ void ath_txq_schedule(struct ath_softc *
+@@ -1692,17 +1856,17 @@ void ath_txq_schedule(struct ath_softc *
                        if (tid->paused)
                                continue;
  
                                break;
                }
  
-@@ -1711,9 +1866,17 @@ void ath_txq_schedule(struct ath_softc *
+@@ -1711,9 +1875,17 @@ void ath_txq_schedule(struct ath_softc *
                        list_add_tail(&ac->list, &txq->axq_acq);
                }
  
        }
  
        rcu_read_unlock();
-@@ -1792,57 +1955,6 @@ static void ath_tx_txqaddbuf(struct ath_
+@@ -1787,62 +1959,13 @@ static void ath_tx_txqaddbuf(struct ath_
+                       if (bf_is_ampdu_not_probing(bf))
+                               txq->axq_ampdu_depth++;
+-                      bf = bf->bf_lastbf->bf_next;
++                      bf_last = bf->bf_lastbf;
++                      bf = bf_last->bf_next;
++                      bf_last->bf_next = NULL;
+               }
        }
  }
  
  static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
                               struct ath_atx_tid *tid, struct sk_buff *skb)
  {
-@@ -1985,6 +2097,7 @@ static int ath_tx_prepare(struct ieee802
+@@ -1985,6 +2108,7 @@ static int ath_tx_prepare(struct ieee802
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_sta *sta = txctl->sta;
        struct ieee80211_vif *vif = info->control.vif;
        struct ath_softc *sc = hw->priv;
        int frmlen = skb->len + FCS_LEN;
        int padpos, padsize;
-@@ -1992,6 +2105,10 @@ static int ath_tx_prepare(struct ieee802
+@@ -1992,6 +2116,10 @@ static int ath_tx_prepare(struct ieee802
        /* NOTE:  sta can be NULL according to net/mac80211.h */
        if (sta)
                txctl->an = (struct ath_node *)sta->drv_priv;
  
        if (info->control.hw_key)
                frmlen += info->control.hw_key->icv_len;
-@@ -2041,7 +2158,6 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -2041,7 +2169,6 @@ int ath_tx_start(struct ieee80211_hw *hw
        struct ath_txq *txq = txctl->txq;
        struct ath_atx_tid *tid = NULL;
        struct ath_buf *bf;
        int q;
        int ret;
  
-@@ -2069,27 +2185,31 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -2069,27 +2196,31 @@ int ath_tx_start(struct ieee80211_hw *hw
                ath_txq_unlock(sc, txq);
                txq = sc->tx.uapsdq;
                ath_txq_lock(sc, txq);
                if (txctl->paprd)
                        dev_kfree_skb_any(skb);
                else
-@@ -2142,7 +2262,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
+@@ -2142,7 +2273,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
  
                bf->bf_lastbf = bf;
                ath_set_rates(vif, NULL, bf);
                duration += info.rates[0].PktDuration;
                if (bf_tail)
                        bf_tail->bf_next = bf;
-@@ -2189,7 +2309,7 @@ static void ath_tx_complete(struct ath_s
+@@ -2189,7 +2320,7 @@ static void ath_tx_complete(struct ath_s
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
        unsigned long flags;
  
        ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
-@@ -2225,21 +2345,7 @@ static void ath_tx_complete(struct ath_s
+@@ -2225,21 +2356,7 @@ static void ath_tx_complete(struct ath_s
        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
  
        __skb_queue_tail(&txq->complete_q, skb);
  }
  
  static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
-@@ -2360,8 +2466,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2360,8 +2477,7 @@ static void ath_tx_processq(struct ath_s
  
                if (list_empty(&txq->axq_q)) {
                        txq->axq_link = NULL;
                        break;
                }
                bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
-@@ -2375,7 +2480,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2375,7 +2491,7 @@ static void ath_tx_processq(struct ath_s
                 * it with the STALE flag.
                 */
                bf_held = NULL;
                        bf_held = bf;
                        if (list_is_last(&bf_held->list, &txq->axq_q))
                                break;
-@@ -2399,7 +2504,7 @@ static void ath_tx_processq(struct ath_s
+@@ -2399,7 +2515,7 @@ static void ath_tx_processq(struct ath_s
                 * however leave the last descriptor back as the holding
                 * descriptor for hw.
                 */
                INIT_LIST_HEAD(&bf_head);
                if (!list_is_singular(&lastbf->list))
                        list_cut_position(&bf_head,
-@@ -2470,7 +2575,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+@@ -2470,7 +2586,7 @@ void ath_tx_edma_tasklet(struct ath_soft
                }
  
                bf = list_first_entry(fifo_list, struct ath_buf, list);
                        list_del(&bf->list);
                        ath_tx_return_buffer(sc, bf);
                        bf = list_first_entry(fifo_list, struct ath_buf, list);
-@@ -2492,7 +2597,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+@@ -2492,7 +2608,7 @@ void ath_tx_edma_tasklet(struct ath_soft
                                ath_tx_txqaddbuf(sc, txq, &bf_q, true);
                        }
                } else {
                        if (bf != lastbf)
                                list_cut_position(&bf_head, fifo_list,
                                                  lastbf->list.prev);
-@@ -2583,6 +2688,7 @@ void ath_tx_node_init(struct ath_softc *
+@@ -2583,6 +2699,7 @@ void ath_tx_node_init(struct ath_softc *
                tid->paused    = false;
                tid->active        = false;
                __skb_queue_head_init(&tid->buf_q);
                acno = TID_TO_WME_AC(tidno);
                tid->ac = &an->ac[acno];
        }
-@@ -2590,6 +2696,7 @@ void ath_tx_node_init(struct ath_softc *
+@@ -2590,6 +2707,7 @@ void ath_tx_node_init(struct ath_softc *
        for (acno = 0, ac = &an->ac[acno];
             acno < IEEE80211_NUM_ACS; acno++, ac++) {
                ac->sched    = false;
         *init dbgp flags before all
 --- a/drivers/net/wireless/rtlwifi/ps.c
 +++ b/drivers/net/wireless/rtlwifi/ps.c
-@@ -269,6 +269,7 @@ void rtl_ips_nic_on(struct ieee80211_hw
+@@ -269,6 +269,7 @@ void rtl_ips_nic_on(struct ieee80211_hw 
  
        spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
  }