|
@@ -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);
|
|
|
|