aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2011-02-22 17:22:30 -0500
committerLuciano Coelho <coelho@ti.com>2011-02-23 04:18:46 -0500
commit09039f42a24084c10e7761ab28ef22932c62a46f (patch)
tree09c46d96003ef58080c3559158c94a7c5dd0b3b7 /drivers/net
parent409622ecc2a3b618b31b1894ed6360fbdca95d62 (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.c11
-rw-r--r--drivers/net/wireless/wl12xx/ps.c2
-rw-r--r--drivers/net/wireless/wl12xx/tx.c53
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h4
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
110static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, 110static 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
152static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, 155static 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 {
322struct wl1271_link { 322struct 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
327struct wl1271 { 331struct wl1271 {