summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 8a1b262..9f5ecef 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -781,8 +781,10 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
skb_pull(skb, sizeof(*tr) - hdrlen);
}
+#define REDUCED_TX_HEADROOM 8
+
static void
-mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad)
+mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad)
{
struct ieee80211_hdr *wh;
int hdrlen;
@@ -798,6 +800,22 @@ mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad)
wh = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_hdrlen(wh->frame_control);
+
+ /*
+ * Check if skb_resize is required because of
+ * tx_headroom adjustment.
+ */
+ if (priv->ap_fw && (hdrlen < (sizeof(struct ieee80211_cts)
+ + REDUCED_TX_HEADROOM))) {
+ if (pskb_expand_head(skb, REDUCED_TX_HEADROOM, 0, GFP_ATOMIC)) {
+
+ wiphy_err(priv->hw->wiphy,
+ "Failed to reallocate TX buffer\n");
+ return;
+ }
+ skb->truesize += REDUCED_TX_HEADROOM;
+ }
+
reqd_hdrlen = sizeof(*tr);
if (hdrlen != reqd_hdrlen)
@@ -820,7 +838,8 @@ mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad)
tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad);
}
-static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
+static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv,
+ struct sk_buff *skb)
{
struct ieee80211_hdr *wh;
struct ieee80211_tx_info *tx_info;
@@ -861,7 +880,7 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
break;
}
}
- mwl8k_add_dma_header(skb, data_pad);
+ mwl8k_add_dma_header(priv, skb, data_pad);
}
/*
@@ -1816,9 +1835,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
mgmtframe = true;
if (priv->ap_fw)
- mwl8k_encapsulate_tx_frame(skb);
+ mwl8k_encapsulate_tx_frame(priv, skb);
else
- mwl8k_add_dma_header(skb, 0);
+ mwl8k_add_dma_header(priv, skb, 0);
wh = &((struct mwl8k_dma_data *)skb->data)->wh;
@@ -5474,6 +5493,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
hw->extra_tx_headroom =
sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts);
+ hw->extra_tx_headroom -= priv->ap_fw ? REDUCED_TX_HEADROOM : 0;
+
hw->channel_change_time = 10;
hw->queues = MWL8K_TX_WMM_QUEUES;