aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorIdo Reis <idor@ti.com>2012-05-13 07:53:40 -0400
committerLuciano Coelho <coelho@ti.com>2012-06-07 11:11:06 -0400
commit9fccc82e19db0d63741cd6c3d2a8829fc8854406 (patch)
tree7fb6f942dc178c9bc648b736927206b2ce7eac95 /drivers/net
parentf5755fe96cb010031a50458e6d1391377d94c275 (diff)
wl18xx: pad only last frame in aggregration buffer for PG2
In PG2 only the last frame in the aggregate buffer should be aligned to the sdio block size. This frame's header msb should be set to 0, while in all the previous frames in the aggregation buffer, this bit should be set to 1. [Add a HW op for setting the frame ctrl bit only for 18xx. Other minor cleanups - Arik] [Make the pre_pkt_send operation optional -- Luca] Signed-off-by: Ido Reis <idor@ti.com> Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c1
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c30
-rw-r--r--drivers/net/wireless/ti/wl18xx/tx.h3
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h9
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c16
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.h4
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h4
7 files changed, 58 insertions, 9 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index f74d76c95a7f..364fb2feffce 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1406,6 +1406,7 @@ static struct wlcore_ops wl12xx_ops = {
1406 .debugfs_init = wl12xx_debugfs_add_files, 1406 .debugfs_init = wl12xx_debugfs_add_files,
1407 .get_spare_blocks = wl12xx_get_spare_blocks, 1407 .get_spare_blocks = wl12xx_get_spare_blocks,
1408 .set_key = wl12xx_set_key, 1408 .set_key = wl12xx_set_key,
1409 .pre_pkt_send = NULL,
1409}; 1410};
1410 1411
1411static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { 1412static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 84f8e27c29ab..fd02795f830c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -600,7 +600,8 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
600 wl->plt_fw_name = WL18XX_FW_NAME; 600 wl->plt_fw_name = WL18XX_FW_NAME;
601 wl->quirks |= WLCORE_QUIRK_NO_ELP | 601 wl->quirks |= WLCORE_QUIRK_NO_ELP |
602 WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED | 602 WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED |
603 WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN; 603 WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN |
604 WLCORE_QUIRK_TX_PAD_LAST_FRAME;
604 605
605 break; 606 break;
606 case CHIP_ID_185x_PG10: 607 case CHIP_ID_185x_PG10:
@@ -847,7 +848,6 @@ wl18xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
847 u32 blks, u32 spare_blks) 848 u32 blks, u32 spare_blks)
848{ 849{
849 desc->wl18xx_mem.total_mem_blocks = blks; 850 desc->wl18xx_mem.total_mem_blocks = blks;
850 desc->wl18xx_mem.reserved = 0;
851} 851}
852 852
853static void 853static void
@@ -856,6 +856,12 @@ wl18xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
856{ 856{
857 desc->length = cpu_to_le16(skb->len); 857 desc->length = cpu_to_le16(skb->len);
858 858
859 /* if only the last frame is to be padded, we unset this bit on Tx */
860 if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME)
861 desc->wl18xx_mem.ctrl = WL18XX_TX_CTRL_NOT_PADDED;
862 else
863 desc->wl18xx_mem.ctrl = 0;
864
859 wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " 865 wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d "
860 "len: %d life: %d mem: %d", desc->hlid, 866 "len: %d life: %d mem: %d", desc->hlid,
861 le16_to_cpu(desc->length), 867 le16_to_cpu(desc->length),
@@ -1152,6 +1158,25 @@ out:
1152 return ret; 1158 return ret;
1153} 1159}
1154 1160
1161static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
1162 u32 buf_offset, u32 last_len)
1163{
1164 if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) {
1165 struct wl1271_tx_hw_descr *last_desc;
1166
1167 /* get the last TX HW descriptor written to the aggr buf */
1168 last_desc = (struct wl1271_tx_hw_descr *)(wl->aggr_buf +
1169 buf_offset - last_len);
1170
1171 /* the last frame is padded up to an SDIO block */
1172 last_desc->wl18xx_mem.ctrl &= ~WL18XX_TX_CTRL_NOT_PADDED;
1173 return ALIGN(buf_offset, WL12XX_BUS_BLOCK_SIZE);
1174 }
1175
1176 /* no modifications */
1177 return buf_offset;
1178}
1179
1155static struct wlcore_ops wl18xx_ops = { 1180static struct wlcore_ops wl18xx_ops = {
1156 .identify_chip = wl18xx_identify_chip, 1181 .identify_chip = wl18xx_identify_chip,
1157 .boot = wl18xx_boot, 1182 .boot = wl18xx_boot,
@@ -1176,6 +1201,7 @@ static struct wlcore_ops wl18xx_ops = {
1176 .handle_static_data = wl18xx_handle_static_data, 1201 .handle_static_data = wl18xx_handle_static_data,
1177 .get_spare_blocks = wl18xx_get_spare_blocks, 1202 .get_spare_blocks = wl18xx_get_spare_blocks,
1178 .set_key = wl18xx_set_key, 1203 .set_key = wl18xx_set_key,
1204 .pre_pkt_send = wl18xx_pre_pkt_send,
1179}; 1205};
1180 1206
1181/* HT cap appropriate for wide channels */ 1207/* HT cap appropriate for wide channels */
diff --git a/drivers/net/wireless/ti/wl18xx/tx.h b/drivers/net/wireless/ti/wl18xx/tx.h
index 8aecaf09da9c..ccddc548e44a 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.h
+++ b/drivers/net/wireless/ti/wl18xx/tx.h
@@ -32,6 +32,9 @@
32#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F 32#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F
33#define WL18XX_TX_STATUS_STAT_BIT_IDX 7 33#define WL18XX_TX_STATUS_STAT_BIT_IDX 7
34 34
35/* Indicates this TX HW frame is not padded to SDIO block size */
36#define WL18XX_TX_CTRL_NOT_PADDED BIT(7)
37
35/* 38/*
36 * The FW uses a special bit to indicate a wide channel should be used in 39 * The FW uses a special bit to indicate a wide channel should be used in
37 * the rate policy. 40 * the rate policy.
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 34e0498727fc..9e7787ba9610 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -188,4 +188,13 @@ wlcore_hw_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
188 return wl->ops->set_key(wl, cmd, vif, sta, key_conf); 188 return wl->ops->set_key(wl, cmd, vif, sta, key_conf);
189} 189}
190 190
191static inline u32
192wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
193{
194 if (wl->ops->pre_pkt_send)
195 return wl->ops->pre_pkt_send(wl, buf_offset, last_len);
196
197 return buf_offset;
198}
199
191#endif 200#endif
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index da9a07d2cf4b..6983e7a829d0 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -178,10 +178,11 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
178unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, 178unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl,
179 unsigned int packet_length) 179 unsigned int packet_length)
180{ 180{
181 if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) 181 if ((wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) ||
182 return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); 182 !(wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN))
183 else
184 return ALIGN(packet_length, WL1271_TX_ALIGN_TO); 183 return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
184 else
185 return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE);
185} 186}
186EXPORT_SYMBOL(wlcore_calc_packet_alignment); 187EXPORT_SYMBOL(wlcore_calc_packet_alignment);
187 188
@@ -662,7 +663,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
662 struct wl12xx_vif *wlvif; 663 struct wl12xx_vif *wlvif;
663 struct sk_buff *skb; 664 struct sk_buff *skb;
664 struct wl1271_tx_hw_descr *desc; 665 struct wl1271_tx_hw_descr *desc;
665 u32 buf_offset = 0; 666 u32 buf_offset = 0, last_len = 0;
666 bool sent_packets = false; 667 bool sent_packets = false;
667 unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; 668 unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
668 int ret; 669 int ret;
@@ -686,6 +687,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
686 * Flush buffer and try again. 687 * Flush buffer and try again.
687 */ 688 */
688 wl1271_skb_queue_head(wl, wlvif, skb); 689 wl1271_skb_queue_head(wl, wlvif, skb);
690
691 buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset,
692 last_len);
689 wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, 693 wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
690 buf_offset, true); 694 buf_offset, true);
691 sent_packets = true; 695 sent_packets = true;
@@ -711,7 +715,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
711 ieee80211_free_txskb(wl->hw, skb); 715 ieee80211_free_txskb(wl->hw, skb);
712 goto out_ack; 716 goto out_ack;
713 } 717 }
714 buf_offset += ret; 718 last_len = ret;
719 buf_offset += last_len;
715 wl->tx_packets_count++; 720 wl->tx_packets_count++;
716 if (has_data) { 721 if (has_data) {
717 desc = (struct wl1271_tx_hw_descr *) skb->data; 722 desc = (struct wl1271_tx_hw_descr *) skb->data;
@@ -721,6 +726,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
721 726
722out_ack: 727out_ack:
723 if (buf_offset) { 728 if (buf_offset) {
729 buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len);
724 wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, 730 wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
725 buf_offset, true); 731 buf_offset, true);
726 sent_packets = true; 732 sent_packets = true;
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h
index 49e441f34839..fa4be1b91135 100644
--- a/drivers/net/wireless/ti/wlcore/tx.h
+++ b/drivers/net/wireless/ti/wlcore/tx.h
@@ -93,9 +93,9 @@ struct wl18xx_tx_mem {
93 u8 total_mem_blocks; 93 u8 total_mem_blocks;
94 94
95 /* 95 /*
96 * always zero 96 * control bits
97 */ 97 */
98 u8 reserved; 98 u8 ctrl;
99} __packed; 99} __packed;
100 100
101/* 101/*
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index e63450072f4d..761a72f4b8d1 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -80,6 +80,7 @@ struct wlcore_ops {
80 struct ieee80211_vif *vif, 80 struct ieee80211_vif *vif,
81 struct ieee80211_sta *sta, 81 struct ieee80211_sta *sta,
82 struct ieee80211_key_conf *key_conf); 82 struct ieee80211_key_conf *key_conf);
83 u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
83}; 84};
84 85
85enum wlcore_partitions { 86enum wlcore_partitions {
@@ -420,6 +421,9 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd,
420/* Some firmwares may not support ELP */ 421/* Some firmwares may not support ELP */
421#define WLCORE_QUIRK_NO_ELP BIT(6) 422#define WLCORE_QUIRK_NO_ELP BIT(6)
422 423
424/* pad only the last frame in the aggregate buffer */
425#define WLCORE_QUIRK_TX_PAD_LAST_FRAME BIT(7)
426
423/* extra header space is required for TKIP */ 427/* extra header space is required for TKIP */
424#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8) 428#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8)
425 429