69030d27a3ef99419e5728129ed9a57aab8f4716
[12.09/openwrt.git] / package / mac80211 / patches / 556-ath9k_fix_rx_race.patch
1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -79,10 +79,6 @@ struct ath_config {
4                        sizeof(struct ath_buf_state));           \
5         } while (0)
6  
7 -#define ATH_RXBUF_RESET(_bf) do {              \
8 -               (_bf)->bf_stale = false;        \
9 -       } while (0)
10 -
11  /**
12   * enum buffer_type - Buffer type flags
13   *
14 @@ -317,6 +313,7 @@ struct ath_rx {
15         struct ath_descdma rxdma;
16         struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
17  
18 +       struct ath_buf *buf_hold;
19         struct sk_buff *frag;
20  
21         u32 ampdu_ref;
22 --- a/drivers/net/wireless/ath/ath9k/recv.c
23 +++ b/drivers/net/wireless/ath/ath9k/recv.c
24 @@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_s
25         struct ath_desc *ds;
26         struct sk_buff *skb;
27  
28 -       ATH_RXBUF_RESET(bf);
29 -
30         ds = bf->bf_desc;
31         ds->ds_link = 0; /* link to null */
32         ds->ds_data = bf->bf_buf_addr;
33 @@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_s
34         sc->rx.rxlink = &ds->ds_link;
35  }
36  
37 +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
38 +{
39 +       if (sc->rx.buf_hold)
40 +               ath_rx_buf_link(sc, sc->rx.buf_hold);
41 +
42 +       sc->rx.buf_hold = bf;
43 +}
44 +
45  static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
46  {
47         /* XXX block beacon interrupts */
48 @@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct 
49  
50         skb = bf->bf_mpdu;
51  
52 -       ATH_RXBUF_RESET(bf);
53         memset(skb->data, 0, ah->caps.rx_status_len);
54         dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
55                                 ah->caps.rx_status_len, DMA_TO_DEVICE);
56 @@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc)
57         if (list_empty(&sc->rx.rxbuf))
58                 goto start_recv;
59  
60 +       sc->rx.buf_hold = NULL;
61         sc->rx.rxlink = NULL;
62         list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
63                 ath_rx_buf_link(sc, bf);
64 @@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_b
65         }
66  
67         bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
68 +       if (bf == sc->rx.buf_hold)
69 +               return NULL;
70 +
71         ds = bf->bf_desc;
72  
73         /*
74 @@ -1391,7 +1400,7 @@ requeue:
75                 if (edma) {
76                         ath_rx_edma_buf_link(sc, qtype);
77                 } else {
78 -                       ath_rx_buf_link(sc, bf);
79 +                       ath_rx_buf_relink(sc, bf);
80                         ath9k_hw_rxena(ah);
81                 }
82         } while (1);