| From d2e9fc141e2aa21f4b35ee27072d84e9aa6e2ba0 Mon Sep 17 00:00:00 2001 |
| From: Helmut Schaa <helmut.schaa@googlemail.com> |
| Date: Fri, 16 Aug 2013 21:39:40 +0200 |
| Subject: ath9k_htc: Restore skb headroom when returning skb to mac80211 |
| |
| From: Helmut Schaa <helmut.schaa@googlemail.com> |
| |
| commit d2e9fc141e2aa21f4b35ee27072d84e9aa6e2ba0 upstream. |
| |
| ath9k_htc adds padding between the 802.11 header and the payload during |
| TX by moving the header. When handing the frame back to mac80211 for TX |
| status handling the header is not moved back into its original position. |
| This can result in a too small skb headroom when entering ath9k_htc |
| again (due to a soft retransmission for example) causing an |
| skb_under_panic oops. |
| |
| Fix this by moving the 802.11 header back into its original position |
| before returning the frame to mac80211 as other drivers like rt2x00 |
| or ath5k do. |
| |
| Reported-by: Marc Kleine-Budde <mkl@blackshift.org> |
| Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> |
| Tested-by: Marc Kleine-Budde <mkl@blackshift.org> |
| Signed-off-by: Marc Kleine-Budde <mkl@blackshift.org> |
| Signed-off-by: John W. Linville <linville@tuxdriver.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c |
| +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c |
| @@ -448,6 +448,7 @@ static void ath9k_htc_tx_process(struct |
| struct ieee80211_conf *cur_conf = &priv->hw->conf; |
| bool txok; |
| int slot; |
| + int hdrlen, padsize; |
| |
| slot = strip_drv_header(priv, skb); |
| if (slot < 0) { |
| @@ -504,6 +505,15 @@ send_mac80211: |
| |
| ath9k_htc_tx_clear_slot(priv, slot); |
| |
| + /* Remove padding before handing frame back to mac80211 */ |
| + hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
| + |
| + padsize = hdrlen & 3; |
| + if (padsize && skb->len > hdrlen + padsize) { |
| + memmove(skb->data + padsize, skb->data, hdrlen); |
| + skb_pull(skb, padsize); |
| + } |
| + |
| /* Send status to mac80211 */ |
| ieee80211_tx_status(priv->hw, skb); |
| } |