cfg80211: do not overwrite the hardware max power setting in the regulatory code...
[openwrt.git] / package / mac80211 / patches / 550-ath9k_optimize_memory_allocation.patch
1 --- a/drivers/net/wireless/ath/ath9k/main.c
2 +++ b/drivers/net/wireless/ath/ath9k/main.c
3 @@ -1291,6 +1291,11 @@ static void ath9k_stop(struct ieee80211_
4         } else
5                 sc->rx.rxlink = NULL;
6  
7 +       if (sc->rx.frag) {
8 +               dev_kfree_skb_any(sc->rx.frag);
9 +               sc->rx.frag = NULL;
10 +       }
11 +
12         /* disable HAL and put h/w to sleep */
13         ath9k_hw_disable(ah);
14         ath9k_hw_configpcipowersave(ah, 1, 1);
15 --- a/drivers/net/wireless/ath/ath9k/recv.c
16 +++ b/drivers/net/wireless/ath/ath9k/recv.c
17 @@ -209,11 +209,6 @@ static int ath_rx_edma_init(struct ath_s
18         int error = 0, i;
19         u32 size;
20  
21 -
22 -       common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN +
23 -                                    ah->caps.rx_status_len,
24 -                                    min(common->cachelsz, (u16)64));
25 -
26         ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
27                                     ah->caps.rx_status_len);
28  
29 @@ -300,12 +295,12 @@ int ath_rx_init(struct ath_softc *sc, in
30         sc->sc_flags &= ~SC_OP_RXFLUSH;
31         spin_lock_init(&sc->rx.rxbuflock);
32  
33 +       common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
34 +                            sc->sc_ah->caps.rx_status_len;
35 +
36         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
37                 return ath_rx_edma_init(sc, nbufs);
38         } else {
39 -               common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
40 -                               min(common->cachelsz, (u16)64));
41 -
42                 ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
43                         common->cachelsz, common->rx_bufsize);
44  
45 @@ -815,15 +810,9 @@ static bool ath9k_rx_accept(struct ath_c
46         if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
47                 return false;
48  
49 -       /*
50 -        * rs_more indicates chained descriptors which can be used
51 -        * to link buffers together for a sort of scatter-gather
52 -        * operation.
53 -        * reject the frame, we don't support scatter-gather yet and
54 -        * the frame is probably corrupt anyway
55 -        */
56 +       /* Only use error bits from the last fragment */
57         if (rx_stats->rs_more)
58 -               return false;
59 +               return true;
60  
61         /*
62          * The rx_stats->rs_status will not be set until the end of the
63 @@ -981,6 +970,10 @@ static int ath9k_rx_skb_preprocess(struc
64         if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
65                 return -EINVAL;
66  
67 +       /* Only use status info from the last fragment */
68 +       if (rx_stats->rs_more)
69 +               return 0;
70 +
71         ath9k_process_rssi(common, hw, hdr, rx_stats);
72  
73         if (ath9k_process_rate(common, hw, rx_stats, rx_status))
74 @@ -1582,7 +1575,7 @@ div_comb_done:
75  int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
76  {
77         struct ath_buf *bf;
78 -       struct sk_buff *skb = NULL, *requeue_skb;
79 +       struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
80         struct ieee80211_rx_status *rxs;
81         struct ath_hw *ah = sc->sc_ah;
82         struct ath_common *common = ath9k_hw_common(ah);
83 @@ -1633,8 +1626,17 @@ int ath_rx_tasklet(struct ath_softc *sc,
84                 if (!skb)
85                         continue;
86  
87 -               hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
88 -               rxs =  IEEE80211_SKB_RXCB(skb);
89 +               /*
90 +                * Take frame header from the first fragment and RX status from
91 +                * the last one.
92 +                */
93 +               if (sc->rx.frag)
94 +                       hdr_skb = sc->rx.frag;
95 +               else
96 +                       hdr_skb = skb;
97 +
98 +               hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
99 +               rxs = IEEE80211_SKB_RXCB(hdr_skb);
100  
101                 ath_debug_stat_rx(sc, &rs);
102  
103 @@ -1643,12 +1645,12 @@ int ath_rx_tasklet(struct ath_softc *sc,
104                  * chain it back at the queue without processing it.
105                  */
106                 if (flush)
107 -                       goto requeue;
108 +                       goto requeue_drop_frag;
109  
110                 retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
111                                                  rxs, &decrypt_error);
112                 if (retval)
113 -                       goto requeue;
114 +                       goto requeue_drop_frag;
115  
116                 rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
117                 if (rs.rs_tstamp > tsf_lower &&
118 @@ -1668,7 +1670,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
119                  * skb and put it at the tail of the sc->rx.rxbuf list for
120                  * processing. */
121                 if (!requeue_skb)
122 -                       goto requeue;
123 +                       goto requeue_drop_frag;
124  
125                 /* Unmap the frame */
126                 dma_unmap_single(sc->dev, bf->bf_buf_addr,
127 @@ -1679,8 +1681,9 @@ int ath_rx_tasklet(struct ath_softc *sc,
128                 if (ah->caps.rx_status_len)
129                         skb_pull(skb, ah->caps.rx_status_len);
130  
131 -               ath9k_rx_skb_postprocess(common, skb, &rs,
132 -                                        rxs, decrypt_error);
133 +               if (!rs.rs_more)
134 +                       ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
135 +                                                rxs, decrypt_error);
136  
137                 /* We will now give hardware our shiny new allocated skb */
138                 bf->bf_mpdu = requeue_skb;
139 @@ -1697,6 +1700,38 @@ int ath_rx_tasklet(struct ath_softc *sc,
140                         break;
141                 }
142  
143 +               if (rs.rs_more) {
144 +                       /*
145 +                        * rs_more indicates chained descriptors which can be
146 +                        * used to link buffers together for a sort of
147 +                        * scatter-gather operation.
148 +                        */
149 +                       if (sc->rx.frag) {
150 +                               /* too many fragments - cannot handle frame */
151 +                               dev_kfree_skb_any(sc->rx.frag);
152 +                               dev_kfree_skb_any(skb);
153 +                               skb = NULL;
154 +                       }
155 +                       sc->rx.frag = skb;
156 +                       goto requeue;
157 +               }
158 +
159 +               if (sc->rx.frag) {
160 +                       int space = skb->len - skb_tailroom(hdr_skb);
161 +
162 +                       sc->rx.frag = NULL;
163 +
164 +                       if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
165 +                               dev_kfree_skb(skb);
166 +                               goto requeue_drop_frag;
167 +                       }
168 +
169 +                       skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
170 +                                                 skb->len);
171 +                       dev_kfree_skb_any(skb);
172 +                       skb = hdr_skb;
173 +               }
174 +
175                 /*
176                  * change the default rx antenna if rx diversity chooses the
177                  * other antenna 3 times in a row.
178 @@ -1722,6 +1757,11 @@ int ath_rx_tasklet(struct ath_softc *sc,
179  
180                 ieee80211_rx(hw, skb);
181  
182 +requeue_drop_frag:
183 +               if (sc->rx.frag) {
184 +                       dev_kfree_skb_any(sc->rx.frag);
185 +                       sc->rx.frag = NULL;
186 +               }
187  requeue:
188                 if (edma) {
189                         list_add_tail(&bf->list, &sc->rx.rxbuf);
190 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
191 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
192 @@ -311,6 +311,8 @@ struct ath_rx {
193         struct ath_descdma rxdma;
194         struct ath_buf *rx_bufptr;
195         struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
196 +
197 +       struct sk_buff *frag;
198  };
199  
200  int ath_startrecv(struct ath_softc *sc);