aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2012-11-28 04:42:40 -0500
committerLuciano Coelho <coelho@ti.com>2012-12-11 05:25:18 -0500
commitf1626fd8983a5bc68ce2879865cce297eb96c0b4 (patch)
tree3e0ee557e1d9755db804e8f97d68c7e896eaa7f6 /drivers
parentc91ec5f3ada86807ea4857fc5793a4efe99c9de3 (diff)
wlcore/wl18xx: change priority calculations for links
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c22
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c41
-rw-r--r--drivers/net/wireless/ti/wl18xx/wl18xx.h38
-rw-r--r--drivers/net/wireless/ti/wlcore/hw_ops.h20
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c18
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h5
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,
1627 hlid); 1627 hlid);
1628} 1628}
1629 1629
1630static bool wl12xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1631 struct wl1271_link *lnk)
1632{
1633 u8 thold;
1634
1635 if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
1636 thold = wl->conf.tx.fast_link_thold;
1637 else
1638 thold = wl->conf.tx.slow_link_thold;
1639
1640 return lnk->allocated_pkts < thold;
1641}
1642
1643static bool wl12xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
1644 struct wl1271_link *lnk)
1645{
1646 /* any link is good for low priority */
1647 return true;
1648}
1649
1630static int wl12xx_setup(struct wl1271 *wl); 1650static int wl12xx_setup(struct wl1271 *wl);
1631 1651
1632static struct wlcore_ops wl12xx_ops = { 1652static struct wlcore_ops wl12xx_ops = {
@@ -1663,6 +1683,8 @@ static struct wlcore_ops wl12xx_ops = {
1663 .channel_switch = wl12xx_cmd_channel_switch, 1683 .channel_switch = wl12xx_cmd_channel_switch,
1664 .pre_pkt_send = NULL, 1684 .pre_pkt_send = NULL,
1665 .set_peer_cap = wl12xx_set_peer_cap, 1685 .set_peer_cap = wl12xx_set_peer_cap,
1686 .lnk_high_prio = wl12xx_lnk_high_prio,
1687 .lnk_low_prio = wl12xx_lnk_low_prio,
1666}; 1688};
1667 1689
1668static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { 1690static 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,
1397 rate_set, hlid); 1397 rate_set, hlid);
1398} 1398}
1399 1399
1400static bool wl18xx_lnk_high_prio(struct wl1271 *wl, u8 hlid,
1401 struct wl1271_link *lnk)
1402{
1403 u8 thold;
1404 struct wl18xx_fw_status_priv *status_priv =
1405 (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
1406 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1407
1408 /* suspended links are never high priority */
1409 if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
1410 return false;
1411
1412 /* the priority thresholds are taken from FW */
1413 if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
1414 thold = status_priv->tx_fast_link_prio_threshold;
1415 else
1416 thold = status_priv->tx_slow_link_prio_threshold;
1417
1418 return lnk->allocated_pkts < thold;
1419}
1420
1421static bool wl18xx_lnk_low_prio(struct wl1271 *wl, u8 hlid,
1422 struct wl1271_link *lnk)
1423{
1424 u8 thold;
1425 struct wl18xx_fw_status_priv *status_priv =
1426 (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv;
1427 u32 suspend_bitmap = le32_to_cpu(status_priv->link_suspend_bitmap);
1428
1429 if (test_bit(hlid, (unsigned long *)&suspend_bitmap))
1430 thold = status_priv->tx_suspend_threshold;
1431 else if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
1432 thold = status_priv->tx_fast_stop_threshold;
1433 else
1434 thold = status_priv->tx_slow_stop_threshold;
1435
1436 return lnk->allocated_pkts < thold;
1437}
1438
1400static int wl18xx_setup(struct wl1271 *wl); 1439static int wl18xx_setup(struct wl1271 *wl);
1401 1440
1402static struct wlcore_ops wl18xx_ops = { 1441static struct wlcore_ops wl18xx_ops = {
@@ -1434,6 +1473,8 @@ static struct wlcore_ops wl18xx_ops = {
1434 .pre_pkt_send = wl18xx_pre_pkt_send, 1473 .pre_pkt_send = wl18xx_pre_pkt_send,
1435 .sta_rc_update = wl18xx_sta_rc_update, 1474 .sta_rc_update = wl18xx_sta_rc_update,
1436 .set_peer_cap = wl18xx_set_peer_cap, 1475 .set_peer_cap = wl18xx_set_peer_cap,
1476 .lnk_high_prio = wl18xx_lnk_high_prio,
1477 .lnk_low_prio = wl18xx_lnk_low_prio,
1437}; 1478};
1438 1479
1439/* HT cap appropriate for wide channels in 2Ghz */ 1480/* 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 {
68 */ 68 */
69 u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC]; 69 u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC];
70 70
71 u8 padding[2]; 71 /* A bitmap representing the currently suspended links. The suspend
72 * is short lived, for multi-channel Tx requirements.
73 */
74 __le32 link_suspend_bitmap;
75
76 /* packet threshold for an "almost empty" AC,
77 * for Tx schedulng purposes
78 */
79 u8 tx_ac_threshold;
80
81 /* number of packets to queue up for a link in PS */
82 u8 tx_ps_threshold;
83
84 /* number of packet to queue up for a suspended link */
85 u8 tx_suspend_threshold;
86
87 /* Should have less than this number of packets in queue of a slow
88 * link to qualify as high priority link
89 */
90 u8 tx_slow_link_prio_threshold;
91
92 /* Should have less than this number of packets in queue of a fast
93 * link to qualify as high priority link
94 */
95 u8 tx_fast_link_prio_threshold;
96
97 /* Should have less than this number of packets in queue of a slow
98 * link before we stop queuing up packets for it.
99 */
100 u8 tx_slow_stop_threshold;
101
102 /* Should have less than this number of packets in queue of a fast
103 * link before we stop queuing up packets for it.
104 */
105 u8 tx_fast_stop_threshold;
106
107 u8 padding[3];
72}; 108};
73 109
74#define WL18XX_PHY_VERSION_MAX_LEN 20 110#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,
222 return 0; 222 return 0;
223} 223}
224 224
225static inline bool
226wlcore_hw_lnk_high_prio(struct wl1271 *wl, u8 hlid,
227 struct wl1271_link *lnk)
228{
229 if (!wl->ops->lnk_high_prio)
230 BUG_ON(1);
231
232 return wl->ops->lnk_high_prio(wl, hlid, lnk);
233}
234
235static inline bool
236wlcore_hw_lnk_low_prio(struct wl1271 *wl, u8 hlid,
237 struct wl1271_link *lnk)
238{
239 if (!wl->ops->lnk_low_prio)
240 BUG_ON(1);
241
242 return wl->ops->lnk_low_prio(wl, hlid, lnk);
243}
244
225#endif 245#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,
509 return skb; 509 return skb;
510} 510}
511 511
512static bool wlcore_lnk_high_prio(struct wl1271 *wl, u8 hlid,
513 struct wl1271_link *lnk)
514{
515 u8 thold;
516
517 if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
518 thold = wl->conf.tx.fast_link_thold;
519 else
520 thold = wl->conf.tx.slow_link_thold;
521
522 return lnk->allocated_pkts < thold;
523}
524
525static struct sk_buff *wlcore_lnk_dequeue_high_prio(struct wl1271 *wl, 512static struct sk_buff *wlcore_lnk_dequeue_high_prio(struct wl1271 *wl,
526 u8 hlid, u8 ac, 513 u8 hlid, u8 ac,
527 u8 *low_prio_hlid) 514 u8 *low_prio_hlid)
528{ 515{
529 struct wl1271_link *lnk = &wl->links[hlid]; 516 struct wl1271_link *lnk = &wl->links[hlid];
530 517
531 if (!wlcore_lnk_high_prio(wl, hlid, lnk)) { 518 if (!wlcore_hw_lnk_high_prio(wl, hlid, lnk)) {
532 if (*low_prio_hlid == WL12XX_INVALID_LINK_ID && 519 if (*low_prio_hlid == WL12XX_INVALID_LINK_ID &&
533 !skb_queue_empty(&lnk->tx_queue[ac])) 520 !skb_queue_empty(&lnk->tx_queue[ac]) &&
521 wlcore_hw_lnk_low_prio(wl, hlid, lnk))
534 /* we found the first non-empty low priority queue */ 522 /* we found the first non-empty low priority queue */
535 *low_prio_hlid = hlid; 523 *low_prio_hlid = hlid;
536 524
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 {
110 struct ieee80211_sta_ht_cap *ht_cap, 110 struct ieee80211_sta_ht_cap *ht_cap,
111 bool allow_ht_operation, 111 bool allow_ht_operation,
112 u32 rate_set, u8 hlid); 112 u32 rate_set, u8 hlid);
113 113 bool (*lnk_high_prio)(struct wl1271 *wl, u8 hlid,
114 struct wl1271_link *lnk);
115 bool (*lnk_low_prio)(struct wl1271 *wl, u8 hlid,
116 struct wl1271_link *lnk);
114}; 117};
115 118
116enum wlcore_partitions { 119enum wlcore_partitions {