wlcore/wl18xx: change priority calculations for links
authorArik Nemtsov <arik@wizery.com>
Wed, 28 Nov 2012 09:42:40 +0000 (11:42 +0200)
committerLuciano Coelho <coelho@ti.com>
Tue, 11 Dec 2012 10:25:18 +0000 (12:25 +0200)
Update the 18xx FW status private part to include Tx related link
priorities. Introduce new HW ops to determine link priority per chip
family.

For 18xx the changes are:
- Suspended links are at most low priority and Tx for them is stopped
  beyond the suspend threshold.
- Active links now get their thresholds directly from FW
- There's a new "stop" threshold for active links, at which point a link
  stops receiving new packets.

Update the min 18xx FW version required to make sure suspended links
bitmap is advertised by the FW.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wl18xx/wl18xx.h
drivers/net/wireless/ti/wlcore/hw_ops.h
drivers/net/wireless/ti/wlcore/tx.c
drivers/net/wireless/ti/wlcore/wlcore.h

index 08b6762..6d4a021 100644 (file)
@@ -1627,6 +1627,26 @@ static int wl12xx_set_peer_cap(struct wl1271 *wl,
                                              hlid);
 }
 
+static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
+                                struct wl1271_link *lnk)
+{
+       u8 thold;
+
+       if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
+               thold = wl->conf.tx.fast_link_thold;
+       else
+               thold = wl->conf.tx.slow_link_thold;
+
+       return lnk->allocated_pkts < thold;
+}
+
+static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
+                               struct wl1271_link *lnk)
+{
+       /* any link is good for low priority */
+       return true;
+}
+
 static int wl12xx_setup(struct wl1271 *wl);
 
 static struct wlcore_ops wl12xx_ops = {
@@ -1663,6 +1683,8 @@ static struct wlcore_ops wl12xx_ops = {
        .channel_switch         = wl12xx_cmd_channel_switch,
        .pre_pkt_send           = NULL,
        .set_peer_cap           = wl12xx_set_peer_cap,
+       .lnk_high_prio          = wl12xx_lnk_high_prio,
+       .lnk_low_prio           = wl12xx_lnk_low_prio,
 };
 
 static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
index a35eba2..ed34a7f 100644 (file)
@@ -1397,6 +1397,45 @@ static int wl18xx_set_peer_cap(struct wl1271 *wl,
                                       rate_set, hlid);
 }
 
+static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
+                                struct wl1271_link *lnk)
+{
+       u8 thold;
+       struct wl18xx_fw_status_priv *status_priv =
+               (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
+       u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+
+       /* suspended links are never high priority */
+       if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
+               return false;
+
+       /* the priority thresholds are taken from FW */
+       if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
+               thold = status_priv->tx_fast_link_prio_threshold;
+       else
+               thold = status_priv->tx_slow_link_prio_threshold;
+
+       return lnk->allocated_pkts < thold;
+}
+
+static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
+                               struct wl1271_link *lnk)
+{
+       u8 thold;
+       struct wl18xx_fw_status_priv *status_priv =
+               (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
+       u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
+
+       if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
+               thold = status_priv->tx_suspend_threshold;
+       else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
+               thold = status_priv->tx_fast_stop_threshold;
+       else
+               thold = status_priv->tx_slow_stop_threshold;
+
+       return lnk->allocated_pkts < thold;
+}
+
 static int wl18xx_setup(struct wl1271 *wl);
 
 static struct wlcore_ops wl18xx_ops = {
@@ -1434,6 +1473,8 @@ static struct wlcore_ops wl18xx_ops = {
        .pre_pkt_send   = wl18xx_pre_pkt_send,
        .sta_rc_update  = wl18xx_sta_rc_update,
        .set_peer_cap   = wl18xx_set_peer_cap,
+       .lnk_high_prio  = wl18xx_lnk_high_prio,
+       .lnk_low_prio   = wl18xx_lnk_low_prio,
 };
 
 /* HT cap appropriate for wide channels in 2Ghz */
index 3105fbf..e6ea78c 100644 (file)
@@ -68,7 +68,43 @@ struct wl18xx_fw_status_priv {
         */
        u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC];
 
-       u8 padding[2];
+       /* A bitmap representing the currently suspended links. The suspend
+        * is short lived, for multi-channel Tx requirements.
+        */
+       __le32 link_suspend_bitmap;
+
+       /* packet threshold for an "almost empty" AC,
+        * for Tx schedulng purposes
+        */
+       u8 tx_ac_threshold;
+
+       /* number of packets to queue up for a link in PS */
+       u8 tx_ps_threshold;
+
+       /* number of packet to queue up for a suspended link */
+       u8 tx_suspend_threshold;
+
+       /* Should have less than this number of packets in queue of a slow
+        * link to qualify as high priority link
+        */
+       u8 tx_slow_link_prio_threshold;
+
+       /* Should have less than this number of packets in queue of a fast
+        * link to qualify as high priority link
+        */
+       u8 tx_fast_link_prio_threshold;
+
+       /* Should have less than this number of packets in queue of a slow
+        * link before we stop queuing up packets for it.
+        */
+       u8 tx_slow_stop_threshold;
+
+       /* Should have less than this number of packets in queue of a fast
+        * link before we stop queuing up packets for it.
+        */
+       u8 tx_fast_stop_threshold;
+
+       u8 padding[3];
 };
 
 #define WL18XX_PHY_VERSION_MAX_LEN 20
index 4db03e1..7fd260c 100644 (file)
@@ -222,4 +222,24 @@ wlcore_hw_set_peer_cap(struct wl1271 *wl,
        return 0;
 }
 
+static inline bool
+wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid,
+                       struct wl1271_link *lnk)
+{
+       if (!wl->ops->lnk_high_prio)
+               BUG_ON(1);
+
+       return wl->ops->lnk_high_prio(wl, hlid, lnk);
+}
+
+static inline bool
+wlcore_hw_lnk_low_prio(struct wl1271 *wl, u8 hlid,
+                      struct wl1271_link *lnk)
+{
+       if (!wl->ops->lnk_low_prio)
+               BUG_ON(1);
+
+       return wl->ops->lnk_low_prio(wl, hlid, lnk);
+}
+
 #endif
index 8f5ea89..25cfd35 100644 (file)
@@ -509,28 +509,16 @@ static struct sk_buff *wlcore_lnk_dequeue(struct wl1271 *wl,
        return skb;
 }
 
-static bool wlcore_lnk_high_prio(struct wl1271 *wl, u8 hlid,
-                                struct wl1271_link *lnk)
-{
-       u8 thold;
-
-       if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
-               thold = wl->conf.tx.fast_link_thold;
-       else
-               thold = wl->conf.tx.slow_link_thold;
-
-       return lnk->allocated_pkts < thold;
-}
-
 static struct sk_buff *wlcore_lnk_dequeue_high_prio(struct wl1271 *wl,
                                                    u8 hlid, u8 ac,
                                                    u8 *low_prio_hlid)
 {
        struct wl1271_link *lnk = &wl->links[hlid];
 
-       if (!wlcore_lnk_high_prio(wl, hlid, lnk)) {
+       if (!wlcore_hw_lnk_high_prio(wl, hlid, lnk)) {
                if (*low_prio_hlid == WL12XX_INVALID_LINK_ID &&
-                   !skb_queue_empty(&lnk->tx_queue[ac]))
+                   !skb_queue_empty(&lnk->tx_queue[ac]) &&
+                   wlcore_hw_lnk_low_prio(wl, hlid, lnk))
                        /* we found the first non-empty low priority queue */
                        *low_prio_hlid = hlid;
 
index a444116..58e5250 100644 (file)
@@ -110,7 +110,10 @@ struct wlcore_ops {
                            struct ieee80211_sta_ht_cap *ht_cap,
                            bool allow_ht_operation,
                            u32 rate_set, u8 hlid);
-
+       bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid,
+                             struct wl1271_link *lnk);
+       bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
+                            struct wl1271_link *lnk);
 };
 
 enum wlcore_partitions {