diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/tx.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 105 |
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 | ||
34 | static 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 | |||
33 | static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | 51 | static 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 | |||
582 | u32 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 | } | ||