diff options
-rw-r--r-- | drivers/net/wireless/ti/wl12xx/main.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/wl18xx.h | 38 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/hw_ops.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/tx.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 5 |
6 files changed, 127 insertions, 17 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 08b67625f7ff..6d4a02171abc 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -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 = { diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index a35eba2b8d8b..ed34a7f3391c 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -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 */ diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index 3105fbf79ae4..e6ea78c7da36 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -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 diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 4db03e14acf7..7fd260c02a0a 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h @@ -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 diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 8f5ea89b03b1..25cfd35ab1a2 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -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; diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index a4441164bb4b..58e52505ec17 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -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 { |