mirror of https://gitee.com/openkylin/linux.git
wl12xx: enable AP advanced functionality
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>
This commit is contained in:
parent
769d7ac62d
commit
9b17f1b371
|
@ -755,8 +755,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
|
||||||
static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
|
|
||||||
{
|
{
|
||||||
bool fw_ps;
|
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
|
* 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);
|
wl1271_ps_link_end(wl, hlid);
|
||||||
|
|
||||||
/* Start high-level PS if the STA is asleep with enough blocks in FW */
|
/* 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);
|
wl1271_ps_link_start(wl, hlid, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wl1271_irq_update_links_status(struct wl1271 *wl,
|
bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
|
||||||
struct wl1271_fw_ap_status *status)
|
{
|
||||||
|
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;
|
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);
|
cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
|
||||||
if (wl->ap_fw_ps_map != cur_fw_ps_map) {
|
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++) {
|
for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
|
||||||
u8 cnt = status->tx_lnk_free_blks[hlid] -
|
if (!wl1271_is_active_sta(wl, hlid))
|
||||||
wl->links[hlid].prev_freed_blks;
|
continue;
|
||||||
|
|
||||||
wl->links[hlid].prev_freed_blks =
|
cnt = status->tx_lnk_free_pkts[hlid] -
|
||||||
status->tx_lnk_free_blks[hlid];
|
wl->links[hlid].prev_freed_pkts;
|
||||||
wl->links[hlid].allocated_blks -= cnt;
|
|
||||||
|
|
||||||
wl1271_irq_ps_regulate_link(wl, hlid,
|
wl->links[hlid].prev_freed_pkts =
|
||||||
wl->links[hlid].allocated_blks);
|
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,
|
static void wl12xx_fw_status(struct wl1271 *wl,
|
||||||
struct wl12xx_fw_status *status)
|
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);
|
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
|
||||||
|
|
||||||
/* for AP update num of allocated TX blocks per link and ps status */
|
/* for AP update num of allocated TX blocks per link and ps status */
|
||||||
if (wl->bss_type == BSS_TYPE_AP_BSS) {
|
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||||
#if 0
|
wl12xx_irq_update_links_status(wl, status);
|
||||||
wl1271_irq_update_links_status(wl, status);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update the host-chipset time offset */
|
/* update the host-chipset time offset */
|
||||||
getnstimeofday(&ts);
|
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);
|
__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,
|
static int wl1271_op_sta_add(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
|
|
|
@ -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))
|
if (test_bit(hlid, &wl->ap_ps_map))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
|
wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
|
||||||
"clean_queues %d", hlid, wl->links[hlid].allocated_blks,
|
"clean_queues %d", hlid, wl->links[hlid].allocated_pkts,
|
||||||
clean_queues);
|
clean_queues);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
|
@ -123,27 +123,25 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
|
||||||
wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
|
wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
|
static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
|
||||||
{
|
{
|
||||||
bool fw_ps;
|
bool fw_ps;
|
||||||
u8 tx_blks;
|
u8 tx_pkts;
|
||||||
|
|
||||||
/* only regulate station links */
|
/* only regulate station links */
|
||||||
if (hlid < WL1271_AP_STA_HLID_START)
|
if (hlid < WL1271_AP_STA_HLID_START)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
|
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
|
* 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.
|
* 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);
|
wl1271_ps_link_start(wl, hlid, true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
|
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));
|
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
|
||||||
wl->tx_allocated_pkts[ac]++;
|
wl->tx_allocated_pkts[ac]++;
|
||||||
|
|
||||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
if (wl->bss_type == BSS_TYPE_AP_BSS &&
|
||||||
wl->links[hlid].allocated_blks += total_blocks;
|
hlid >= WL1271_AP_STA_HLID_START)
|
||||||
|
wl->links[hlid].allocated_pkts++;
|
||||||
|
|
||||||
ret = 0;
|
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) {
|
if (wl->bss_type == BSS_TYPE_AP_BSS) {
|
||||||
wl1271_tx_ap_update_inconnection_sta(wl, skb);
|
wl1271_tx_ap_update_inconnection_sta(wl, skb);
|
||||||
#if 0
|
|
||||||
wl1271_tx_regulate_link(wl, hlid);
|
wl1271_tx_regulate_link(wl, hlid);
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
wl1271_tx_update_filters(wl, skb);
|
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) {
|
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);
|
wl1271_tx_reset_link_queues(wl, i);
|
||||||
wl->links[i].allocated_blks = 0;
|
wl->links[i].allocated_pkts = 0;
|
||||||
wl->links[i].prev_freed_blks = 0;
|
wl->links[i].prev_freed_pkts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl->last_tx_hlid = 0;
|
wl->last_tx_hlid = 0;
|
||||||
|
|
|
@ -152,15 +152,14 @@ extern u32 wl12xx_debug_level;
|
||||||
#define WL1271_AP_STA_HLID_START 3
|
#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
|
* 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
|
* 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
|
* 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.
|
* 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_BSS_INDEX 0
|
||||||
#define WL1271_AP_DEF_BEACON_EXP 20
|
#define WL1271_AP_DEF_BEACON_EXP 20
|
||||||
|
@ -237,8 +236,12 @@ struct wl1271_stats {
|
||||||
|
|
||||||
#define AP_MAX_STATIONS 5
|
#define AP_MAX_STATIONS 5
|
||||||
|
|
||||||
/* Broadcast and Global links + links to stations */
|
/* Broadcast and Global links + system link + links to stations */
|
||||||
#define AP_MAX_LINKS (AP_MAX_STATIONS + 2)
|
/*
|
||||||
|
* 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 */
|
/* FW status registers */
|
||||||
struct wl12xx_fw_status {
|
struct wl12xx_fw_status {
|
||||||
|
@ -271,8 +274,8 @@ struct wl12xx_fw_status {
|
||||||
/* Cumulative counter of released packets per AC */
|
/* Cumulative counter of released packets per AC */
|
||||||
u8 tx_released_pkts[NUM_TX_QUEUES];
|
u8 tx_released_pkts[NUM_TX_QUEUES];
|
||||||
|
|
||||||
/* Cumulative counter of freed MBs per HLID */
|
/* Cumulative counter of freed packets per HLID */
|
||||||
u8 tx_lnk_free_blks[WL12XX_MAX_LINKS];
|
u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
|
||||||
|
|
||||||
/* Cumulative counter of released Voice memory blocks */
|
/* Cumulative counter of released Voice memory blocks */
|
||||||
u8 tx_voice_released_blks;
|
u8 tx_voice_released_blks;
|
||||||
|
@ -351,9 +354,9 @@ struct wl1271_link {
|
||||||
/* AP-mode - TX queue per AC in link */
|
/* AP-mode - TX queue per AC in link */
|
||||||
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
|
struct sk_buff_head tx_queue[NUM_TX_QUEUES];
|
||||||
|
|
||||||
/* accounting for allocated / available TX blocks in FW */
|
/* accounting for allocated / freed packets in FW */
|
||||||
u8 allocated_blks;
|
u8 allocated_pkts;
|
||||||
u8 prev_freed_blks;
|
u8 prev_freed_pkts;
|
||||||
|
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue