Commit 84b313b3 authored by Xinming Hu's avatar Xinming Hu Committed by Kalle Valo

mwifiex: make tx packet 64 byte DMA aligned

This patch adds support for DMA alignment of 64 bytes for TX packets.
Signed-off-by: default avatarXinming Hu <huxm@marvell.com>
Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 2ab87d5d
...@@ -101,6 +101,13 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, ...@@ -101,6 +101,13 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
{ {
struct txpd *local_tx_pd; struct txpd *local_tx_pd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
unsigned int pad;
int headroom = (priv->adapter->iface_type ==
MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
pad = ((void *)skb->data - sizeof(*local_tx_pd) -
headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
skb_push(skb, pad);
skb_push(skb, sizeof(*local_tx_pd)); skb_push(skb, sizeof(*local_tx_pd));
...@@ -114,10 +121,12 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, ...@@ -114,10 +121,12 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
local_tx_pd->bss_num = priv->bss_num; local_tx_pd->bss_num = priv->bss_num;
local_tx_pd->bss_type = priv->bss_type; local_tx_pd->bss_type = priv->bss_type;
/* Always zero as the data is followed by struct txpd */ /* Always zero as the data is followed by struct txpd */
local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) +
pad);
local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
sizeof(*local_tx_pd)); sizeof(*local_tx_pd) -
pad);
if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
...@@ -182,7 +191,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, ...@@ -182,7 +191,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
ra_list_flags); ra_list_flags);
return -1; return -1;
} }
skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN);
tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr);
memset(tx_info_aggr, 0, sizeof(*tx_info_aggr)); memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));
......
...@@ -32,9 +32,12 @@ ...@@ -32,9 +32,12 @@
#define MWIFIEX_MAX_BSS_NUM (3) #define MWIFIEX_MAX_BSS_NUM (3)
#define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) #define MWIFIEX_DMA_ALIGN_SZ 64
* + 4 byte alignment #define MAX_TXPD_SZ 32
*/ #define INTF_HDR_ALIGN 4
#define MWIFIEX_MIN_DATA_HEADER_LEN (MWIFIEX_DMA_ALIGN_SZ + INTF_HDR_ALIGN + \
MAX_TXPD_SZ)
#define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8 /* sizeof(pkt_type) #define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8 /* sizeof(pkt_type)
* + sizeof(tx_control) * + sizeof(tx_control)
*/ */
......
...@@ -47,8 +47,10 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, ...@@ -47,8 +47,10 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_adapter *adapter = priv->adapter;
struct txpd *local_tx_pd; struct txpd *local_tx_pd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
u8 pad; unsigned int pad;
u16 pkt_type, pkt_offset; u16 pkt_type, pkt_offset;
int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
INTF_HEADER_LEN;
if (!skb->len) { if (!skb->len) {
dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len);
...@@ -56,13 +58,12 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, ...@@ -56,13 +58,12 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
return skb->data; return skb->data;
} }
pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
/* If skb->data is not aligned; add padding */ pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN pad = ((void *)skb->data - (sizeof(*local_tx_pd) + hroom)-
+ pad)); NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
skb_push(skb, sizeof(*local_tx_pd) + pad); skb_push(skb, sizeof(*local_tx_pd) + pad);
local_tx_pd = (struct txpd *) skb->data; local_tx_pd = (struct txpd *) skb->data;
...@@ -70,8 +71,8 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, ...@@ -70,8 +71,8 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
local_tx_pd->bss_num = priv->bss_num; local_tx_pd->bss_num = priv->bss_num;
local_tx_pd->bss_type = priv->bss_type; local_tx_pd->bss_type = priv->bss_type;
local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len - local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len -
(sizeof(struct txpd) (sizeof(struct txpd) +
+ pad))); pad)));
local_tx_pd->priority = (u8) skb->priority; local_tx_pd->priority = (u8) skb->priority;
local_tx_pd->pkt_delay_2ms = local_tx_pd->pkt_delay_2ms =
...@@ -115,7 +116,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, ...@@ -115,7 +116,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,
local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset); local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset);
/* make space for INTF_HEADER_LEN */ /* make space for INTF_HEADER_LEN */
skb_push(skb, INTF_HEADER_LEN); skb_push(skb, hroom);
if (!local_tx_pd->tx_control) if (!local_tx_pd->tx_control)
/* TxCtrl set by user or default */ /* TxCtrl set by user or default */
......
...@@ -348,8 +348,10 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, ...@@ -348,8 +348,10 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_adapter *adapter = priv->adapter;
struct uap_txpd *txpd; struct uap_txpd *txpd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
int pad, len; int pad;
u16 pkt_type; u16 pkt_type, pkt_offset;
int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 :
INTF_HEADER_LEN;
if (!skb->len) { if (!skb->len) {
dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len);
...@@ -357,22 +359,21 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, ...@@ -357,22 +359,21 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
return skb->data; return skb->data;
} }
pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN);
/* If skb->data is not aligned, add padding */
pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4;
len = sizeof(*txpd) + pad; pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
BUG_ON(skb_headroom(skb) < len + INTF_HEADER_LEN); pad = ((void *)skb->data - (sizeof(*txpd) + hroom) - NULL) &
(MWIFIEX_DMA_ALIGN_SZ - 1);
skb_push(skb, len); skb_push(skb, sizeof(*txpd) + pad);
txpd = (struct uap_txpd *)skb->data; txpd = (struct uap_txpd *)skb->data;
memset(txpd, 0, sizeof(*txpd)); memset(txpd, 0, sizeof(*txpd));
txpd->bss_num = priv->bss_num; txpd->bss_num = priv->bss_num;
txpd->bss_type = priv->bss_type; txpd->bss_type = priv->bss_type;
txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - len)); txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - (sizeof(*txpd) +
pad)));
txpd->priority = (u8)skb->priority; txpd->priority = (u8)skb->priority;
txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb); txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
...@@ -392,16 +393,17 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, ...@@ -392,16 +393,17 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv,
cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]); cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]);
/* Offset of actual data */ /* Offset of actual data */
pkt_offset = sizeof(*txpd) + pad;
if (pkt_type == PKT_TYPE_MGMT) { if (pkt_type == PKT_TYPE_MGMT) {
/* Set the packet type and add header for management frame */ /* Set the packet type and add header for management frame */
txpd->tx_pkt_type = cpu_to_le16(pkt_type); txpd->tx_pkt_type = cpu_to_le16(pkt_type);
len += MWIFIEX_MGMT_FRAME_HEADER_SIZE; pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE;
} }
txpd->tx_pkt_offset = cpu_to_le16(len); txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
/* make space for INTF_HEADER_LEN */ /* make space for INTF_HEADER_LEN */
skb_push(skb, INTF_HEADER_LEN); skb_push(skb, hroom);
if (!txpd->tx_control) if (!txpd->tx_control)
/* TxCtrl set by user or default */ /* TxCtrl set by user or default */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment