diff --git a/dma.c b/dma.c index 6dd6a61c..d8f61e54 100644 --- a/dma.c +++ b/dma.c @@ -310,6 +310,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, txwi = mt76_get_txwi_ptr(dev, t); skb->prev = skb->next = NULL; + if (dev->drv->tx_aligned4_skbs) + mt76_insert_hdr_pad(skb); len = skb_headlen(skb); addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE); diff --git a/mt76.h b/mt76.h index 6301f1af..00ae1d68 100644 --- a/mt76.h +++ b/mt76.h @@ -292,6 +292,7 @@ struct mt76_hw_cap { #define MT_TXWI_NO_FREE BIT(0) struct mt76_driver_ops { + bool tx_aligned4_skbs; u32 txwi_flags; u16 txwi_size; @@ -675,6 +676,20 @@ static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb) return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data); } +static inline void mt76_insert_hdr_pad(struct sk_buff *skb) +{ + int len = ieee80211_get_hdrlen_from_skb(skb); + + if (len % 4 == 0) + return; + + skb_push(skb, 2); + memmove(skb->data, skb->data + 2, len); + + skb->data[len] = 0; + skb->data[len + 1] = 0; +} + static inline bool mt76_is_skb_pktid(u8 pktid) { if (pktid & MT_PACKET_ID_HAS_RATE) diff --git a/mt76x0/pci.c b/mt76x0/pci.c index 246c0fd5..4585e1b7 100644 --- a/mt76x0/pci.c +++ b/mt76x0/pci.c @@ -153,6 +153,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), + .tx_aligned4_skbs = true, .update_survey = mt76x02_update_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb, diff --git a/mt76x02_txrx.c b/mt76x02_txrx.c index 40a1e8b7..82acebb7 100644 --- a/mt76x02_txrx.c +++ b/mt76x02_txrx.c @@ -154,19 +154,17 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt76x02_txwi *txwi = txwi_ptr; - struct sk_buff *skb = tx_info->skb; - int hdrlen, pad, len, pid, qsel = MT_QSEL_EDCA; - bool ampdu = IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU; + bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; + int hdrlen, len, pid, qsel = MT_QSEL_EDCA; if (qid == MT_TXQ_PSD && wcid && wcid->idx < 128) mt76x02_mac_wcid_set_drop(dev, wcid->idx, false); hdrlen = ieee80211_hdrlen(hdr->frame_control); - pad = skb->len > hdrlen ? (hdrlen & 2) : 0; - len = skb->len - pad; - mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); + len = tx_info->skb->len - (hdrlen & 2); + mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len); - pid = mt76_tx_status_skb_add(mdev, wcid, skb); + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); /* encode packet rate for no-skb packet id to fix up status reporting */ if (pid == MT_PACKET_ID_NO_SKB) diff --git a/mt76x02_usb_core.c b/mt76x02_usb_core.c index 2cc190a9..f3696afc 100644 --- a/mt76x02_usb_core.c +++ b/mt76x02_usb_core.c @@ -77,21 +77,19 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, struct mt76_tx_info *tx_info) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); - struct sk_buff *skb = tx_info->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int pid, hdrlen, len = skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx); - bool ampdu = IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU; + int pid, len = tx_info->skb->len, ep = q2ep(mdev->q_tx[qid].q->hw_idx); struct mt76x02_txwi *txwi; + bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; enum mt76_qsel qsel; u32 flags; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - len -= skb->len > hdrlen ? (hdrlen & 2) : 0; - txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi)); - mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len); - skb_push(skb, sizeof(struct mt76x02_txwi)); + mt76_insert_hdr_pad(tx_info->skb); - pid = mt76_tx_status_skb_add(mdev, wcid, skb); + txwi = (struct mt76x02_txwi *)(tx_info->skb->data - sizeof(*txwi)); + mt76x02_mac_write_txwi(dev, txwi, tx_info->skb, wcid, sta, len); + skb_push(tx_info->skb, sizeof(*txwi)); + + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); /* encode packet rate for no-skb packet id to fix up status reporting */ if (pid == MT_PACKET_ID_NO_SKB) diff --git a/mt76x02_util.c b/mt76x02_util.c index 55e43e1f..ad532344 100644 --- a/mt76x02_util.c +++ b/mt76x02_util.c @@ -138,6 +138,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev) hw->max_rates = 1; hw->max_report_rates = 7; hw->max_rate_tries = 1; + hw->extra_tx_headroom = 2; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | @@ -173,7 +174,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev) hw->sta_data_size = sizeof(struct mt76x02_sta); hw->vif_data_size = sizeof(struct mt76x02_vif); - ieee80211_hw_set(hw, TX_NEEDS_ALIGNED4_SKBS); ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); diff --git a/mt76x2/pci.c b/mt76x2/pci.c index cab00d0b..e84d5c59 100644 --- a/mt76x2/pci.c +++ b/mt76x2/pci.c @@ -32,6 +32,7 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct mt76_driver_ops drv_ops = { .txwi_size = sizeof(struct mt76x02_txwi), + .tx_aligned4_skbs = true, .update_survey = mt76x02_update_channel, .tx_prepare_skb = mt76x02_tx_prepare_skb, .tx_complete_skb = mt76x02_tx_complete_skb,