Root/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);
201

Archive Download this file



interactive