wl12xx: AP-mode - count free FW TX blocks per link
authorArik Nemtsov <arik@wizery.com>
Tue, 22 Feb 2011 22:22:30 +0000 (00:22 +0200)
committerLuciano Coelho <coelho@ti.com>
Wed, 23 Feb 2011 09:18:46 +0000 (11:18 +0200)
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>
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/wl12xx.h

index 92f8220433317f3752d74ed3fbdbd554e26733fd..5772a33d79ecab92e9bfaa6cbe188c442670363b 100644 (file)
@@ -574,6 +574,17 @@ static void wl1271_fw_status(struct wl1271 *wl,
        if (total)
                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 */
        getnstimeofday(&ts);
        wl->time_offset = (timespec_to_ns(&ts) >> 10) -
index 2d3086ae633866630baabc54c6f582042d3db832..b7b3139e00fb00c1921aa95497add7547dc8e95c 100644 (file)
@@ -172,5 +172,3 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 
        return ret;
 }
-
-
index de60b4bc4a7288137794ab482ff8160a0b3ba45c..ea1382bd38f401d12b690e2000f4a81b455e8d6e 100644 (file)
@@ -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,
-                               u32 buf_offset)
+                               u32 buf_offset, u8 hlid)
 {
        struct wl1271_tx_hw_descr *desc;
        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,
 
                wl->tx_blocks_available -= total_blocks;
 
+               if (wl->bss_type == BSS_TYPE_AP_BSS)
+                       wl->links[hlid].allocated_blks += total_blocks;
+
                ret = 0;
 
                wl1271_debug(DEBUG_TX,
@@ -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,
-                             u32 extra, struct ieee80211_tx_info *control)
+                             u32 extra, struct ieee80211_tx_info *control,
+                             u8 hlid)
 {
        struct timespec ts;
        struct wl1271_tx_hw_descr *desc;
@@ -186,7 +190,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
        desc->tid = ac;
 
        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)
                   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,
                else
                        rate_idx = ACX_TX_BASIC_RATE;
        } else {
-               if (control->control.sta) {
-                       struct wl1271_station *wl_sta;
-
-                       wl_sta = (struct wl1271_station *)
-                                       control->control.sta->drv_priv;
-                       desc->hlid = wl_sta->hlid;
+               desc->hlid = hlid;
+               switch (hlid) {
+               case WL1271_AP_GLOBAL_HLID:
+                       rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
+                       break;
+               case WL1271_AP_BROADCAST_HLID:
+                       rate_idx = ACX_TX_AP_MODE_BCST_RATE;
+                       break;
+               default:
                        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;
-                       } else {
-                               desc->hlid = WL1271_AP_BROADCAST_HLID;
-                               rate_idx = ACX_TX_AP_MODE_BCST_RATE;
-                       }
+                       break;
                }
        }
 
@@ -245,6 +241,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
        u32 extra = 0;
        int ret = 0;
        u32 total_len;
+       u8 hlid;
 
        if (!skb)
                return -EINVAL;
@@ -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)
                return ret;
 
        if (wl->bss_type == BSS_TYPE_AP_BSS)
                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
@@ -635,8 +637,11 @@ void wl1271_tx_reset(struct wl1271 *wl)
 
        /* TX failure */
        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);
+                       wl->links[i].allocated_blks = 0;
+                       wl->links[i].prev_freed_blks = 0;
+               }
 
                wl->last_tx_hlid = 0;
        } else {
index 9ffac80d39887f890c1bab4ecc7b955d714ed6c9..0e00c5be99d371b88998f0416529c2f61594527b 100644 (file)
@@ -322,6 +322,10 @@ enum wl12xx_flags {
 struct wl1271_link {
        /* AP-mode - TX queue per AC in link */
        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 {