550-ath9k_optimize_memory_allocation.patch 5.6 KB

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