From d420961afd1ae2ca8590ee2c79defc0a48fa8e73 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 18 Feb 2019 14:39:38 +0100 Subject: [PATCH] mt76x02: make sure probe request skb's are 4 bytes aligned We add 2 bytes header pad if header length is not multiple of 4 bytes, this assure most tx skb buffers are 4 bytes aligned. But this is not true for probe request frames which have n*4 bytes header length and are not aligned. I think is ok to assume that frames have to be 4 bytes aligned for DMA purpose, so mt76 driver should take care of that. Signed-off-by: Stanislaw Gruszka --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 5 +--- .../net/wireless/mediatek/mt76/mt76x02_usb_core.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 32 +++++++++++++++------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6d96766a6ed3..ad329db7de4e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -155,7 +155,7 @@ void mt76x02_set_tx_ackto(struct mt76x02_dev *dev); void mt76x02_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class); int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val); -int mt76x02_insert_hdr_pad(struct sk_buff *skb); +void mt76x02_align_skb(struct sk_buff *skb); void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len); bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update); void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index a5413a309a0a..63c5520a65ca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -163,7 +163,6 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76x02_txwi *txwi = txwi_ptr; int qsel = MT_QSEL_EDCA; int pid; - int ret; if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128) mt76x02_mac_wcid_set_drop(dev, wcid->idx, false); @@ -173,9 +172,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, pid = mt76_tx_status_skb_add(mdev, wcid, skb); txwi->pktid = pid; - ret = mt76x02_insert_hdr_pad(skb); - if (ret < 0) - return ret; + mt76x02_align_skb(skb); if (pid >= MT_PACKET_ID_FIRST) qsel = MT_QSEL_MGMT; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 098d05e109e7..bd5838c26f43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -79,7 +79,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, u32 flags; int pid; - mt76x02_insert_hdr_pad(skb); + mt76x02_align_skb(skb); txwi = skb_push(skb, sizeof(struct mt76x02_txwi)); mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 062614ad0d51..08425b1d2c30 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -550,21 +550,33 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(mt76x02_sta_rate_tbl_update); -int mt76x02_insert_hdr_pad(struct sk_buff *skb) +void mt76x02_align_skb(struct sk_buff *skb) { - int len = ieee80211_get_hdrlen_from_skb(skb); + int align = ((unsigned long) skb->data) & 3; + int hdrlen, skblen; - if (len % 4 == 0) - return 0; + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + WARN_ON_ONCE(align == 0 && (hdrlen & 3)); + + if (align == 0) + return; - skb_push(skb, 2); - memmove(skb->data, skb->data + 2, len); + if (hdrlen & 3) { + /* Align frame and add 2 bytes pad after header. */ + skb_push(skb, 2); + memmove(skb->data, skb->data + 2, hdrlen); - skb->data[len] = 0; - skb->data[len + 1] = 0; - return 2; + skb->data[hdrlen] = 0; + skb->data[hdrlen + 1] = 0; + } else { + /* Only for probe request frames. */ + skblen = skb->len; + skb_push(skb, 2); + memmove(skb->data, skb->data + 2, skblen); + skb_trim(skb, skblen); + } } -EXPORT_SYMBOL_GPL(mt76x02_insert_hdr_pad); +EXPORT_SYMBOL_GPL(mt76x02_align_skb); void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len) { -- 2.7.5