aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/tx.c')
-rw-r--r--drivers/net/wireless/wl12xx/tx.c105
1 files changed, 90 insertions, 15 deletions
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index b44c75cd8c1e..3507c81c7500 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -23,6 +23,7 @@
23 23
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/etherdevice.h>
26 27
27#include "wl12xx.h" 28#include "wl12xx.h"
28#include "io.h" 29#include "io.h"
@@ -30,6 +31,23 @@
30#include "ps.h" 31#include "ps.h"
31#include "tx.h" 32#include "tx.h"
32 33
34static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
35{
36 int ret;
37 bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
38
39 if (is_ap)
40 ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
41 else
42 ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
43
44 if (ret < 0)
45 return ret;
46
47 wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id);
48 return 0;
49}
50
33static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) 51static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
34{ 52{
35 int id; 53 int id;
@@ -99,7 +117,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
99{ 117{
100 struct timespec ts; 118 struct timespec ts;
101 struct wl1271_tx_hw_descr *desc; 119 struct wl1271_tx_hw_descr *desc;
102 int pad, ac; 120 int pad, ac, rate_idx;
103 s64 hosttime; 121 s64 hosttime;
104 u16 tx_attr; 122 u16 tx_attr;
105 123
@@ -117,7 +135,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
117 getnstimeofday(&ts); 135 getnstimeofday(&ts);
118 hosttime = (timespec_to_ns(&ts) >> 10); 136 hosttime = (timespec_to_ns(&ts) >> 10);
119 desc->start_time = cpu_to_le32(hosttime - wl->time_offset); 137 desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
120 desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); 138
139 if (wl->bss_type != BSS_TYPE_AP_BSS)
140 desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
141 else
142 desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
121 143
122 /* configure the tx attributes */ 144 /* configure the tx attributes */
123 tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; 145 tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
@@ -125,7 +147,41 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
125 /* queue (we use same identifiers for tid's and ac's */ 147 /* queue (we use same identifiers for tid's and ac's */
126 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); 148 ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
127 desc->tid = ac; 149 desc->tid = ac;
128 desc->aid = TX_HW_DEFAULT_AID; 150
151 if (wl->bss_type != BSS_TYPE_AP_BSS) {
152 desc->aid = TX_HW_DEFAULT_AID;
153
154 /* if the packets are destined for AP (have a STA entry)
155 send them with AP rate policies, otherwise use default
156 basic rates */
157 if (control->control.sta)
158 rate_idx = ACX_TX_AP_FULL_RATE;
159 else
160 rate_idx = ACX_TX_BASIC_RATE;
161 } else {
162 if (control->control.sta) {
163 struct wl1271_station *wl_sta;
164
165 wl_sta = (struct wl1271_station *)
166 control->control.sta->drv_priv;
167 desc->hlid = wl_sta->hlid;
168 rate_idx = ac;
169 } else {
170 struct ieee80211_hdr *hdr;
171
172 hdr = (struct ieee80211_hdr *)
173 (skb->data + sizeof(*desc));
174 if (ieee80211_is_mgmt(hdr->frame_control)) {
175 desc->hlid = WL1271_AP_GLOBAL_HLID;
176 rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
177 } else {
178 desc->hlid = WL1271_AP_BROADCAST_HLID;
179 rate_idx = ACX_TX_AP_MODE_BCST_RATE;
180 }
181 }
182 }
183
184 tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
129 desc->reserved = 0; 185 desc->reserved = 0;
130 186
131 /* align the length (and store in terms of words) */ 187 /* align the length (and store in terms of words) */
@@ -136,14 +192,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
136 pad = pad - skb->len; 192 pad = pad - skb->len;
137 tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; 193 tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
138 194
139 /* if the packets are destined for AP (have a STA entry) send them
140 with AP rate policies, otherwise use default basic rates */
141 if (control->control.sta)
142 tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
143
144 desc->tx_attr = cpu_to_le16(tx_attr); 195 desc->tx_attr = cpu_to_le16(tx_attr);
145 196
146 wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); 197 wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
198 "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
199 le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
200 le16_to_cpu(desc->life_time), desc->total_mem_blocks);
147} 201}
148 202
149/* caller must hold wl->mutex */ 203/* caller must hold wl->mutex */
@@ -153,7 +207,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
153 struct ieee80211_tx_info *info; 207 struct ieee80211_tx_info *info;
154 u32 extra = 0; 208 u32 extra = 0;
155 int ret = 0; 209 int ret = 0;
156 u8 idx;
157 u32 total_len; 210 u32 total_len;
158 211
159 if (!skb) 212 if (!skb)
@@ -166,11 +219,15 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
166 extra = WL1271_TKIP_IV_SPACE; 219 extra = WL1271_TKIP_IV_SPACE;
167 220
168 if (info->control.hw_key) { 221 if (info->control.hw_key) {
169 idx = info->control.hw_key->hw_key_idx; 222 bool is_wep;
223 u8 idx = info->control.hw_key->hw_key_idx;
224 u32 cipher = info->control.hw_key->cipher;
225
226 is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
227 (cipher == WLAN_CIPHER_SUITE_WEP104);
170 228
171 /* FIXME: do we have to do this if we're not using WEP? */ 229 if (unlikely(is_wep && wl->default_key != idx)) {
172 if (unlikely(wl->default_key != idx)) { 230 ret = wl1271_set_default_wep_key(wl, idx);
173 ret = wl1271_cmd_set_default_wep_key(wl, idx);
174 if (ret < 0) 231 if (ret < 0)
175 return ret; 232 return ret;
176 wl->default_key = idx; 233 wl->default_key = idx;
@@ -303,7 +360,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
303 woken_up = true; 360 woken_up = true;
304 361
305 wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); 362 wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
306 wl1271_acx_rate_policies(wl); 363 wl1271_acx_sta_rate_policies(wl);
307 } 364 }
308 365
309 while ((skb = wl1271_skb_dequeue(wl))) { 366 while ((skb = wl1271_skb_dequeue(wl))) {
@@ -521,3 +578,21 @@ void wl1271_tx_flush(struct wl1271 *wl)
521 578
522 wl1271_warning("Unable to flush all TX buffers, timed out."); 579 wl1271_warning("Unable to flush all TX buffers, timed out.");
523} 580}
581
582u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
583{
584 int i;
585 u32 rate = 0;
586
587 if (!wl->basic_rate_set) {
588 WARN_ON(1);
589 wl->basic_rate_set = wl->conf.tx.basic_rate;
590 }
591
592 for (i = 0; !rate; i++) {
593 if ((wl->basic_rate_set >> i) & 0x1)
594 rate = 1 << i;
595 }
596
597 return rate;
598}