Skip to content

Commit

Permalink
wl12xx: enable AP advanced functionality
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arik Nemtsov authored and Luciano Coelho committed Aug 22, 2011
1 parent 769d7ac commit 9b17f1b
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 51 deletions.
54 changes: 27 additions & 27 deletions drivers/net/wireless/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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) {
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/wl12xx/ps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
19 changes: 8 additions & 11 deletions drivers/net/wireless/wl12xx/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
25 changes: 14 additions & 11 deletions drivers/net/wireless/wl12xx/wl12xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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];

Expand Down

0 comments on commit 9b17f1b

Please sign in to comment.