wl12xx: enable AP advanced functionality
authorArik Nemtsov <arik@wizery.com>
Sun, 14 Aug 2011 10:17:35 +0000 (13:17 +0300)
committerLuciano Coelho <coelho@ti.com>
Mon, 22 Aug 2011 09:35:31 +0000 (12:35 +0300)
This adjusts FW TX block allocation for connected stations in PS.
Firmware congestion is measured in allocated packets instead of blocks.

Allow a link in PS to queue up to 2 packets to the FW.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@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 0fa3a22..ad0b5a1 100644 (file)
@@ -755,8 +755,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
        return ret;
 }
 
-#if 0
-static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
+static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
 {
        bool fw_ps;
 
@@ -768,21 +767,29 @@ static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
 
        /*
         * Wake up from high level PS if the STA is asleep with too little
-        * blocks in FW or if the STA is awake.
+        * packets in FW or if the STA is awake.
         */
-       if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
+       if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
                wl1271_ps_link_end(wl, hlid);
 
        /* Start high-level PS if the STA is asleep with enough blocks in FW */
-       else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+       else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
                wl1271_ps_link_start(wl, hlid, true);
 }
 
-static void wl1271_irq_update_links_status(struct wl1271 *wl,
-                                      struct wl1271_fw_ap_status *status)
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
+{
+       int id = hlid - WL1271_AP_STA_HLID_START;
+       return test_bit(id, wl->ap_hlid_map);
+}
+
+static void wl12xx_irq_update_links_status(struct wl1271 *wl,
+                                          struct wl12xx_fw_status *status)
 {
        u32 cur_fw_ps_map;
-       u8 hlid;
+       u8 hlid, cnt;
+
+       /* TODO: also use link_fast_bitmap here */
 
        cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
        if (wl->ap_fw_ps_map != cur_fw_ps_map) {
@@ -795,18 +802,20 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
        }
 
        for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
-               u8 cnt = status->tx_lnk_free_blks[hlid] -
-                       wl->links[hlid].prev_freed_blks;
+               if (!wl1271_is_active_sta(wl, hlid))
+                       continue;
 
-               wl->links[hlid].prev_freed_blks =
-                       status->tx_lnk_free_blks[hlid];
-               wl->links[hlid].allocated_blks -= cnt;
+               cnt = status->tx_lnk_free_pkts[hlid] -
+                     wl->links[hlid].prev_freed_pkts;
 
-               wl1271_irq_ps_regulate_link(wl, hlid,
-                                           wl->links[hlid].allocated_blks);
+               wl->links[hlid].prev_freed_pkts =
+                       status->tx_lnk_free_pkts[hlid];
+               wl->links[hlid].allocated_pkts -= cnt;
+
+               wl12xx_irq_ps_regulate_link(wl, hlid,
+                                           wl->links[hlid].allocated_pkts);
        }
 }
-#endif
 
 static void wl12xx_fw_status(struct wl1271 *wl,
                             struct wl12xx_fw_status *status)
@@ -865,11 +874,8 @@ static void wl12xx_fw_status(struct wl1271 *wl,
                clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
 
        /* for AP update num of allocated TX blocks per link and ps status */
-       if (wl->bss_type == BSS_TYPE_AP_BSS) {
-#if 0
-               wl1271_irq_update_links_status(wl, status);
-#endif
-       }
+       if (wl->bss_type == BSS_TYPE_AP_BSS)
+               wl12xx_irq_update_links_status(wl, status);
 
        /* update the host-chipset time offset */
        getnstimeofday(&ts);
@@ -3711,12 +3717,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
        __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 }
 
-bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
-{
-       int id = hlid - WL1271_AP_STA_HLID_START;
-       return test_bit(id, wl->ap_hlid_map);
-}
-
 static int wl1271_op_sta_add(struct ieee80211_hw *hw,
                             struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta)
index 3548377..4b720b1 100644 (file)
@@ -226,8 +226,8 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
        if (test_bit(hlid, &wl->ap_ps_map))
                return;
 
-       wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
-                    "clean_queues %d", hlid, wl->links[hlid].allocated_blks,
+       wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
+                    "clean_queues %d", hlid, wl->links[hlid].allocated_pkts,
                     clean_queues);
 
        rcu_read_lock();
index ccbcd0a..0f15785 100644 (file)
@@ -123,27 +123,25 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
                wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
 }
 
-#if 0
 static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
 {
        bool fw_ps;
-       u8 tx_blks;
+       u8 tx_pkts;
 
        /* only regulate station links */
        if (hlid < WL1271_AP_STA_HLID_START)
                return;
 
        fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
-       tx_blks = wl->links[hlid].allocated_blks;
+       tx_pkts = wl->links[hlid].allocated_pkts;
 
        /*
         * if in FW PS and there is enough data in FW we can put the link
         * into high-level PS and clean out its TX queues.
         */
-       if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+       if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
                wl1271_ps_link_start(wl, hlid, true);
 }
-#endif
 
 static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
 {
@@ -245,8 +243,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
                ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
                wl->tx_allocated_pkts[ac]++;
 
-               if (wl->bss_type == BSS_TYPE_AP_BSS)
-                       wl->links[hlid].allocated_blks += total_blocks;
+               if (wl->bss_type == BSS_TYPE_AP_BSS &&
+                   hlid >= WL1271_AP_STA_HLID_START)
+                       wl->links[hlid].allocated_pkts++;
 
                ret = 0;
 
@@ -414,9 +413,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 
        if (wl->bss_type == BSS_TYPE_AP_BSS) {
                wl1271_tx_ap_update_inconnection_sta(wl, skb);
-#if 0
                wl1271_tx_regulate_link(wl, hlid);
-#endif
        } else {
                wl1271_tx_update_filters(wl, skb);
        }
@@ -888,8 +885,8 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
        if (wl->bss_type == BSS_TYPE_AP_BSS) {
                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->links[i].allocated_pkts = 0;
+                       wl->links[i].prev_freed_pkts = 0;
                }
 
                wl->last_tx_hlid = 0;
index 6118df5..61a7c21 100644 (file)
@@ -152,15 +152,14 @@ extern u32 wl12xx_debug_level;
 #define WL1271_AP_STA_HLID_START   3
 
 /*
- * When in AP-mode, we allow (at least) this number of mem-blocks
+ * When in AP-mode, we allow (at least) this number of packets
  * to be transmitted to FW for a STA in PS-mode. Only when packets are
  * present in the FW buffers it will wake the sleeping STA. We want to put
  * enough packets for the driver to transmit all of its buffered data before
- * the STA goes to sleep again. But we don't want to take too much mem-blocks
+ * the STA goes to sleep again. But we don't want to take too much memory
  * as it might hurt the throughput of active STAs.
- * The number of blocks (18) is enough for 2 large packets.
  */
-#define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)
+#define WL1271_PS_STA_MAX_PACKETS  2
 
 #define WL1271_AP_BSS_INDEX        0
 #define WL1271_AP_DEF_BEACON_EXP   20
@@ -237,8 +236,12 @@ struct wl1271_stats {
 
 #define AP_MAX_STATIONS            5
 
-/* Broadcast and Global links + links to stations */
-#define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
+/* Broadcast and Global links + system link + links to stations */
+/*
+ * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
+ * the places that use this.
+ */
+#define AP_MAX_LINKS               (AP_MAX_STATIONS + 3)
 
 /* FW status registers */
 struct wl12xx_fw_status {
@@ -271,8 +274,8 @@ struct wl12xx_fw_status {
        /* Cumulative counter of released packets per AC */
        u8 tx_released_pkts[NUM_TX_QUEUES];
 
-       /* Cumulative counter of freed MBs per HLID */
-       u8 tx_lnk_free_blks[WL12XX_MAX_LINKS];
+       /* Cumulative counter of freed packets per HLID */
+       u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
 
        /* Cumulative counter of released Voice memory blocks */
        u8 tx_voice_released_blks;
@@ -351,9 +354,9 @@ 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;
+       /* accounting for allocated / freed packets in FW */
+       u8 allocated_pkts;
+       u8 prev_freed_pkts;
 
        u8 addr[ETH_ALEN];