aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/tx.c
diff options
context:
space:
mode:
authorShahar Levi <shahar_levi@ti.com>2011-03-06 16:32:08 +0200
committerLuciano Coelho <coelho@ti.com>2011-04-19 16:19:47 +0300
commit48a61477bdc04896bd96d259388a0c42a7019943 (patch)
treed36c7638d2405a63db333713a5c7897d736011a5 /drivers/net/wireless/wl12xx/tx.c
parent5aa42346bba2e385674eb1dd4019dfce4c2ef771 (diff)
downloadkernel_samsung_smdk4412-48a61477bdc04896bd96d259388a0c42a7019943.zip
kernel_samsung_smdk4412-48a61477bdc04896bd96d259388a0c42a7019943.tar.gz
kernel_samsung_smdk4412-48a61477bdc04896bd96d259388a0c42a7019943.tar.bz2
wl12xx: 1281/1283 support - Add acx commands
New acx command that sets: Rx fifo enable reduced bus transactions in RX path. Tx bus transactions padding to SDIO block size that improve preference in Tx and essential for working with SDIO HS (48Mhz). The max SDIO block size is 256 when working with Tx bus transactions padding to SDIO block. Add new ops to SDIO & SPI that handles the win size change in case of transactions padding (relevant only for SDIO). [Fix endianess issues; simplify sdio-specific block_size handling; minor changes in comments; use "aligned_len" in one calculation instead of "pad" to avoid confusion -- Luca] Signed-off-by: Shahar Levi <shahar_levi@ti.com> Reviewed-by: Luciano Coelho <coelho@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/tx.c')
-rw-r--r--drivers/net/wireless/wl12xx/tx.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 5e9ef7d..e296f0a 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -132,6 +132,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
{
struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
+ u32 len;
u32 total_blocks;
int id, ret = -EBUSY;
@@ -145,14 +146,20 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
/* approximate the number of blocks required for this packet
in the firmware */
- total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
- total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
+ if (wl->block_size)
+ len = ALIGN(total_len, wl->block_size);
+ else
+ len = total_len;
+
+ total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
+ TX_HW_BLOCK_SPARE;
+
if (total_blocks <= wl->tx_blocks_available) {
desc = (struct wl1271_tx_hw_descr *)skb_push(
skb, total_len - skb->len);
- desc->extra_mem_blocks = TX_HW_BLOCK_SPARE;
- desc->total_mem_blocks = total_blocks;
+ desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE;
+ desc->wl127x_mem.total_mem_blocks = total_blocks;
desc->id = id;
wl->tx_blocks_available -= total_blocks;
@@ -178,7 +185,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
{
struct timespec ts;
struct wl1271_tx_hw_descr *desc;
- int pad, ac, rate_idx;
+ int aligned_len, ac, rate_idx;
s64 hosttime;
u16 tx_attr;
@@ -237,20 +244,32 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
desc->reserved = 0;
- /* align the length (and store in terms of words) */
- pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
- desc->length = cpu_to_le16(pad >> 2);
+ if (wl->block_size) {
+ aligned_len = ALIGN(skb->len, wl->block_size);
+
+ desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
+ desc->length = cpu_to_le16(aligned_len >> 2);
+ } else {
+ int pad;
+
+ /* align the length (and store in terms of words) */
+ aligned_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
+ desc->length = cpu_to_le16(aligned_len >> 2);
+
+ /* calculate number of padding bytes */
+ pad = aligned_len - skb->len;
+ tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
- /* calculate number of padding bytes */
- pad = pad - skb->len;
- tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: padding: %d", pad);
+ }
desc->tx_attr = cpu_to_le16(tx_attr);
- wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
- "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
- le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
- le16_to_cpu(desc->life_time), desc->total_mem_blocks);
+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d tx_attr: 0x%x "
+ "len: %d life: %d mem: %d",
+ desc->hlid, le16_to_cpu(desc->tx_attr),
+ le16_to_cpu(desc->length), le16_to_cpu(desc->life_time),
+ desc->wl127x_mem.total_mem_blocks);
}
/* caller must hold wl->mutex */
@@ -305,11 +324,18 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
/*
- * The length of each packet is stored in terms of words. Thus, we must
- * pad the skb data to make sure its length is aligned.
- * The number of padding bytes is computed and set in wl1271_tx_fill_hdr
+ * The length of each packet is stored in terms of
+ * words. Thus, we must pad the skb data to make sure its
+ * length is aligned. The number of padding bytes is computed
+ * and set in wl1271_tx_fill_hdr.
+ * In special cases, we want to align to a specific block size
+ * (eg. for wl128x with SDIO we align to 256).
*/
- total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
+ if (wl->block_size)
+ total_len = ALIGN(skb->len, wl->block_size);
+ else
+ total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
+
memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);