diff options
author | Arik Nemtsov <arik@wizery.com> | 2011-02-22 17:22:30 -0500 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-02-23 04:18:46 -0500 |
commit | 09039f42a24084c10e7761ab28ef22932c62a46f (patch) | |
tree | 09c46d96003ef58080c3559158c94a7c5dd0b3b7 /drivers/net | |
parent | 409622ecc2a3b618b31b1894ed6360fbdca95d62 (diff) |
wl12xx: AP-mode - count free FW TX blocks per link
Count the number of FW TX blocks allocated per link. We add blocks to a
link counter when allocated for a TX descriptor. We remove blocks
according to counters in fw_status indicating the number of freed blocks
in FW. These counters are polled after each IRQ.
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/wl12xx/main.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/ps.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 4 |
4 files changed, 44 insertions, 26 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 92f822043331..5772a33d79ec 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -574,6 +574,17 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
574 | if (total) | 574 | if (total) |
575 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 575 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
576 | 576 | ||
577 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | ||
578 | for (i = 0; i < AP_MAX_LINKS; i++) { | ||
579 | u8 cnt = status->tx_lnk_free_blks[i] - | ||
580 | wl->links[i].prev_freed_blks; | ||
581 | |||
582 | wl->links[i].prev_freed_blks = | ||
583 | status->tx_lnk_free_blks[i]; | ||
584 | wl->links[i].allocated_blks -= cnt; | ||
585 | } | ||
586 | } | ||
587 | |||
577 | /* update the host-chipset time offset */ | 588 | /* update the host-chipset time offset */ |
578 | getnstimeofday(&ts); | 589 | getnstimeofday(&ts); |
579 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 590 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 2d3086ae6338..b7b3139e00fb 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -172,5 +172,3 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, | |||
172 | 172 | ||
173 | return ret; | 173 | return ret; |
174 | } | 174 | } |
175 | |||
176 | |||
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index de60b4bc4a72..ea1382bd38f4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -108,7 +108,7 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, | 110 | static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, |
111 | u32 buf_offset) | 111 | u32 buf_offset, u8 hlid) |
112 | { | 112 | { |
113 | struct wl1271_tx_hw_descr *desc; | 113 | struct wl1271_tx_hw_descr *desc; |
114 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; | 114 | u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; |
@@ -137,6 +137,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, | |||
137 | 137 | ||
138 | wl->tx_blocks_available -= total_blocks; | 138 | wl->tx_blocks_available -= total_blocks; |
139 | 139 | ||
140 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
141 | wl->links[hlid].allocated_blks += total_blocks; | ||
142 | |||
140 | ret = 0; | 143 | ret = 0; |
141 | 144 | ||
142 | wl1271_debug(DEBUG_TX, | 145 | wl1271_debug(DEBUG_TX, |
@@ -150,7 +153,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, | |||
150 | } | 153 | } |
151 | 154 | ||
152 | static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | 155 | static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, |
153 | u32 extra, struct ieee80211_tx_info *control) | 156 | u32 extra, struct ieee80211_tx_info *control, |
157 | u8 hlid) | ||
154 | { | 158 | { |
155 | struct timespec ts; | 159 | struct timespec ts; |
156 | struct wl1271_tx_hw_descr *desc; | 160 | struct wl1271_tx_hw_descr *desc; |
@@ -186,7 +190,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
186 | desc->tid = ac; | 190 | desc->tid = ac; |
187 | 191 | ||
188 | if (wl->bss_type != BSS_TYPE_AP_BSS) { | 192 | if (wl->bss_type != BSS_TYPE_AP_BSS) { |
189 | desc->aid = TX_HW_DEFAULT_AID; | 193 | desc->aid = hlid; |
190 | 194 | ||
191 | /* if the packets are destined for AP (have a STA entry) | 195 | /* if the packets are destined for AP (have a STA entry) |
192 | send them with AP rate policies, otherwise use default | 196 | send them with AP rate policies, otherwise use default |
@@ -196,25 +200,17 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
196 | else | 200 | else |
197 | rate_idx = ACX_TX_BASIC_RATE; | 201 | rate_idx = ACX_TX_BASIC_RATE; |
198 | } else { | 202 | } else { |
199 | if (control->control.sta) { | 203 | desc->hlid = hlid; |
200 | struct wl1271_station *wl_sta; | 204 | switch (hlid) { |
201 | 205 | case WL1271_AP_GLOBAL_HLID: | |
202 | wl_sta = (struct wl1271_station *) | 206 | rate_idx = ACX_TX_AP_MODE_MGMT_RATE; |
203 | control->control.sta->drv_priv; | 207 | break; |
204 | desc->hlid = wl_sta->hlid; | 208 | case WL1271_AP_BROADCAST_HLID: |
209 | rate_idx = ACX_TX_AP_MODE_BCST_RATE; | ||
210 | break; | ||
211 | default: | ||
205 | rate_idx = ac; | 212 | rate_idx = ac; |
206 | } else { | 213 | break; |
207 | struct ieee80211_hdr *hdr; | ||
208 | |||
209 | hdr = (struct ieee80211_hdr *) | ||
210 | (skb->data + sizeof(*desc)); | ||
211 | if (ieee80211_is_mgmt(hdr->frame_control)) { | ||
212 | desc->hlid = WL1271_AP_GLOBAL_HLID; | ||
213 | rate_idx = ACX_TX_AP_MODE_MGMT_RATE; | ||
214 | } else { | ||
215 | desc->hlid = WL1271_AP_BROADCAST_HLID; | ||
216 | rate_idx = ACX_TX_AP_MODE_BCST_RATE; | ||
217 | } | ||
218 | } | 214 | } |
219 | } | 215 | } |
220 | 216 | ||
@@ -245,6 +241,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
245 | u32 extra = 0; | 241 | u32 extra = 0; |
246 | int ret = 0; | 242 | int ret = 0; |
247 | u32 total_len; | 243 | u32 total_len; |
244 | u8 hlid; | ||
248 | 245 | ||
249 | if (!skb) | 246 | if (!skb) |
250 | return -EINVAL; | 247 | return -EINVAL; |
@@ -271,14 +268,19 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
271 | } | 268 | } |
272 | } | 269 | } |
273 | 270 | ||
274 | ret = wl1271_tx_allocate(wl, skb, extra, buf_offset); | 271 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
272 | hlid = wl1271_tx_get_hlid(skb); | ||
273 | else | ||
274 | hlid = TX_HW_DEFAULT_AID; | ||
275 | |||
276 | ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid); | ||
275 | if (ret < 0) | 277 | if (ret < 0) |
276 | return ret; | 278 | return ret; |
277 | 279 | ||
278 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 280 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
279 | wl1271_tx_ap_update_inconnection_sta(wl, skb); | 281 | wl1271_tx_ap_update_inconnection_sta(wl, skb); |
280 | 282 | ||
281 | wl1271_tx_fill_hdr(wl, skb, extra, info); | 283 | wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); |
282 | 284 | ||
283 | /* | 285 | /* |
284 | * The length of each packet is stored in terms of words. Thus, we must | 286 | * The length of each packet is stored in terms of words. Thus, we must |
@@ -635,8 +637,11 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
635 | 637 | ||
636 | /* TX failure */ | 638 | /* TX failure */ |
637 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 639 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
638 | for (i = 0; i < AP_MAX_LINKS; i++) | 640 | for (i = 0; i < AP_MAX_LINKS; i++) { |
639 | wl1271_tx_reset_link_queues(wl, i); | 641 | wl1271_tx_reset_link_queues(wl, i); |
642 | wl->links[i].allocated_blks = 0; | ||
643 | wl->links[i].prev_freed_blks = 0; | ||
644 | } | ||
640 | 645 | ||
641 | wl->last_tx_hlid = 0; | 646 | wl->last_tx_hlid = 0; |
642 | } else { | 647 | } else { |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9ffac80d3988..0e00c5be99d3 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -322,6 +322,10 @@ enum wl12xx_flags { | |||
322 | struct wl1271_link { | 322 | struct wl1271_link { |
323 | /* AP-mode - TX queue per AC in link */ | 323 | /* AP-mode - TX queue per AC in link */ |
324 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; | 324 | struct sk_buff_head tx_queue[NUM_TX_QUEUES]; |
325 | |||
326 | /* accounting for allocated / available TX blocks in FW */ | ||
327 | u8 allocated_blks; | ||
328 | u8 prev_freed_blks; | ||
325 | }; | 329 | }; |
326 | 330 | ||
327 | struct wl1271 { | 331 | struct wl1271 { |