Commit 09039f42 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho

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: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 409622ec
...@@ -574,6 +574,17 @@ static void wl1271_fw_status(struct wl1271 *wl, ...@@ -574,6 +574,17 @@ static void wl1271_fw_status(struct wl1271 *wl,
if (total) if (total)
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
if (wl->bss_type == BSS_TYPE_AP_BSS) {
for (i = 0; i < AP_MAX_LINKS; i++) {
u8 cnt = status->tx_lnk_free_blks[i] -
wl->links[i].prev_freed_blks;
wl->links[i].prev_freed_blks =
status->tx_lnk_free_blks[i];
wl->links[i].allocated_blks -= cnt;
}
}
/* update the host-chipset time offset */ /* update the host-chipset time offset */
getnstimeofday(&ts); getnstimeofday(&ts);
wl->time_offset = (timespec_to_ns(&ts) >> 10) - wl->time_offset = (timespec_to_ns(&ts) >> 10) -
......
...@@ -172,5 +172,3 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, ...@@ -172,5 +172,3 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
return ret; return ret;
} }
...@@ -108,7 +108,7 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb) ...@@ -108,7 +108,7 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
} }
static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 buf_offset) u32 buf_offset, u8 hlid)
{ {
struct wl1271_tx_hw_descr *desc; struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; 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,6 +137,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
wl->tx_blocks_available -= total_blocks; wl->tx_blocks_available -= total_blocks;
if (wl->bss_type == BSS_TYPE_AP_BSS)
wl->links[hlid].allocated_blks += total_blocks;
ret = 0; ret = 0;
wl1271_debug(DEBUG_TX, wl1271_debug(DEBUG_TX,
...@@ -150,7 +153,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, ...@@ -150,7 +153,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
} }
static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
u32 extra, struct ieee80211_tx_info *control) u32 extra, struct ieee80211_tx_info *control,
u8 hlid)
{ {
struct timespec ts; struct timespec ts;
struct wl1271_tx_hw_descr *desc; struct wl1271_tx_hw_descr *desc;
...@@ -186,7 +190,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, ...@@ -186,7 +190,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
desc->tid = ac; desc->tid = ac;
if (wl->bss_type != BSS_TYPE_AP_BSS) { if (wl->bss_type != BSS_TYPE_AP_BSS) {
desc->aid = TX_HW_DEFAULT_AID; desc->aid = hlid;
/* if the packets are destined for AP (have a STA entry) /* if the packets are destined for AP (have a STA entry)
send them with AP rate policies, otherwise use default 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,25 +200,17 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else else
rate_idx = ACX_TX_BASIC_RATE; rate_idx = ACX_TX_BASIC_RATE;
} else { } else {
if (control->control.sta) { desc->hlid = hlid;
struct wl1271_station *wl_sta; switch (hlid) {
case WL1271_AP_GLOBAL_HLID:
wl_sta = (struct wl1271_station *)
control->control.sta->drv_priv;
desc->hlid = wl_sta->hlid;
rate_idx = ac;
} else {
struct ieee80211_hdr *hdr;
hdr = (struct ieee80211_hdr *)
(skb->data + sizeof(*desc));
if (ieee80211_is_mgmt(hdr->frame_control)) {
desc->hlid = WL1271_AP_GLOBAL_HLID;
rate_idx = ACX_TX_AP_MODE_MGMT_RATE; rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
} else { break;
desc->hlid = WL1271_AP_BROADCAST_HLID; case WL1271_AP_BROADCAST_HLID:
rate_idx = ACX_TX_AP_MODE_BCST_RATE; rate_idx = ACX_TX_AP_MODE_BCST_RATE;
} break;
default:
rate_idx = ac;
break;
} }
} }
...@@ -245,6 +241,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, ...@@ -245,6 +241,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
u32 extra = 0; u32 extra = 0;
int ret = 0; int ret = 0;
u32 total_len; u32 total_len;
u8 hlid;
if (!skb) if (!skb)
return -EINVAL; return -EINVAL;
...@@ -271,14 +268,19 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, ...@@ -271,14 +268,19 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
} }
} }
ret = wl1271_tx_allocate(wl, skb, extra, buf_offset); if (wl->bss_type == BSS_TYPE_AP_BSS)
hlid = wl1271_tx_get_hlid(skb);
else
hlid = TX_HW_DEFAULT_AID;
ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (wl->bss_type == BSS_TYPE_AP_BSS) if (wl->bss_type == BSS_TYPE_AP_BSS)
wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_fill_hdr(wl, skb, extra, info); wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
/* /*
* The length of each packet is stored in terms of words. Thus, we must * 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,8 +637,11 @@ void wl1271_tx_reset(struct wl1271 *wl)
/* TX failure */ /* TX failure */
if (wl->bss_type == BSS_TYPE_AP_BSS) { if (wl->bss_type == BSS_TYPE_AP_BSS) {
for (i = 0; i < AP_MAX_LINKS; i++) for (i = 0; i < AP_MAX_LINKS; i++) {
wl1271_tx_reset_link_queues(wl, i); wl1271_tx_reset_link_queues(wl, i);
wl->links[i].allocated_blks = 0;
wl->links[i].prev_freed_blks = 0;
}
wl->last_tx_hlid = 0; wl->last_tx_hlid = 0;
} else { } else {
......
...@@ -322,6 +322,10 @@ enum wl12xx_flags { ...@@ -322,6 +322,10 @@ enum wl12xx_flags {
struct wl1271_link { struct wl1271_link {
/* AP-mode - TX queue per AC in link */ /* AP-mode - TX queue per AC in link */
struct sk_buff_head tx_queue[NUM_TX_QUEUES]; struct sk_buff_head tx_queue[NUM_TX_QUEUES];
/* accounting for allocated / available TX blocks in FW */
u8 allocated_blks;
u8 prev_freed_blks;
}; };
struct wl1271 { struct wl1271 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment