From: Eliad Peller <eliad@wizery.com>
To: Luciano Coelho <coelho@ti.com>
Cc: <linux-wireless@vger.kernel.org>
Subject: [PATCH v2 36/40] wl12xx: enable AP advanced functionality
Date: Sun, 14 Aug 2011 13:17:35 +0300 [thread overview]
Message-ID: <1313317059-16567-37-git-send-email-eliad@wizery.com> (raw)
In-Reply-To: <1313317059-16567-1-git-send-email-eliad@wizery.com>
From: Arik Nemtsov <arik@wizery.com>
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>
---
drivers/net/wireless/wl12xx/main.c | 54 +++++++++++++++++-----------------
drivers/net/wireless/wl12xx/ps.c | 4 +-
drivers/net/wireless/wl12xx/tx.c | 19 +++++-------
drivers/net/wireless/wl12xx/wl12xx.h | 25 +++++++++-------
4 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 7be7fc6..3d323b8 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -752,64 +752,73 @@ static int wl1271_plt_init(struct wl1271 *wl)
kfree(wl->target_mem_map);
wl->target_mem_map = NULL;
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;
/* only regulate station links */
if (hlid < WL1271_AP_STA_HLID_START)
return;
fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
/*
* 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) {
wl1271_debug(DEBUG_PSM,
"link ps prev 0x%x cur 0x%x changed 0x%x",
wl->ap_fw_ps_map, cur_fw_ps_map,
wl->ap_fw_ps_map ^ cur_fw_ps_map);
wl->ap_fw_ps_map = cur_fw_ps_map;
}
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)
{
struct timespec ts;
u32 old_tx_blk_count = wl->tx_blocks_available;
@@ -862,17 +871,14 @@ static void wl12xx_fw_status(struct wl1271 *wl,
/* if more blocks are available now, tx work can be scheduled */
if (wl->tx_blocks_available > old_tx_blk_count)
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);
wl->time_offset = (timespec_to_ns(&ts) >> 10) -
(s64)le32_to_cpu(status->fw_localtime);
}
@@ -3708,18 +3714,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
wl->links[hlid].ba_bitmap = 0;
wl1271_tx_reset_link_queues(wl, hlid);
__clear_bit(hlid, &wl->ap_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,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct wl1271 *wl = hw->priv;
int ret = 0;
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 3548377..4b720b1 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -223,14 +223,14 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
{
struct ieee80211_sta *sta;
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();
sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
if (!sta) {
wl1271_error("could not find sta %pM for starting ps",
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ccbcd0a..0f15785 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -120,33 +120,31 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
hdr = (struct ieee80211_hdr *)(skb->data +
sizeof(struct wl1271_tx_hw_descr));
if (ieee80211_is_auth(hdr->frame_control))
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)
{
return wl->dummy_packet == skb;
}
@@ -242,14 +240,15 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
wl->tx_blocks_available -= total_blocks;
wl->tx_allocated_blocks += total_blocks;
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;
wl1271_debug(DEBUG_TX,
"tx_allocate: size: %d, blocks: %d, id: %d",
total_len, total_blocks, id);
@@ -411,15 +410,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
return ret;
wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
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);
}
/*
* The length of each packet is stored in terms of
@@ -885,14 +882,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
struct ieee80211_tx_info *info;
/* TX failure */
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;
} else {
for (i = 0; i < NUM_TX_QUEUES; i++) {
while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 6118df5..61a7c21 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -149,21 +149,20 @@ extern u32 wl12xx_debug_level;
* TODO: we currently don't support multirole. remove
* this constant from the code when we do.
*/
#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
#define ACX_TX_DESCRIPTORS 16
@@ -234,14 +233,18 @@ struct wl1271_stats {
#define NUM_TX_QUEUES 4
#define NUM_RX_PKT_DESC 8
#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 {
__le32 intr;
u8 fw_rx_counter;
u8 drv_rx_counter;
@@ -268,14 +271,14 @@ struct wl12xx_fw_status {
/* Size (in Memory Blocks) of TX pool */
__le32 tx_total;
/* 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;
u8 padding_1[7];
__le32 log_start_addr;
} __packed;
@@ -348,15 +351,15 @@ enum wl12xx_flags {
};
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];
/* bitmap of TIDs where RX BA sessions are active for this link */
u8 ba_bitmap;
};
--
1.7.6.401.g6a319
next prev parent reply other threads:[~2011-08-14 10:18 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
2011-08-14 10:17 ` [PATCH v2 01/40] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy" Eliad Peller
2011-08-14 10:17 ` [PATCH v2 02/40] wl12xx: Use a single fw for both STA and AP roles Eliad Peller
2011-08-14 10:17 ` [PATCH v2 03/40] wl12xx: use 1 spare block in all cases Eliad Peller
2011-08-14 10:17 ` [PATCH v2 04/40] wl12xx: temporarily disable advanced ap functions Eliad Peller
2011-08-14 10:17 ` [PATCH v2 05/40] wl12xx: remove rx filtering stuff Eliad Peller
2011-08-14 10:17 ` [PATCH v2 06/40] wl12xx: update fw status struct Eliad Peller
2011-08-14 10:17 ` [PATCH v2 07/40] wl12xx: update acx commands Eliad Peller
2011-08-14 10:17 ` [PATCH v2 08/40] wl12xx: update commands & events Eliad Peller
2011-08-14 10:17 ` [PATCH v2 09/40] wl12xx: enable/disable role on interface add/remove Eliad Peller
2011-08-14 10:17 ` [PATCH v2 10/40] wl12xx: add device role commands Eliad Peller
2011-08-14 10:17 ` [PATCH v2 11/40] wl12xx: update scan cmd api Eliad Peller
2011-08-14 10:17 ` [PATCH v2 12/40] wl12xx: update rx/tx Eliad Peller
2011-08-14 10:17 ` [PATCH v2 13/40] wl12xx: change max/default template size Eliad Peller
2011-08-14 10:17 ` [PATCH v2 14/40] wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap Eliad Peller
2011-08-14 10:17 ` [PATCH v2 15/40] wl12xx: add set_rate_mgmt_params acx Eliad Peller
2011-08-14 10:17 ` [PATCH v2 16/40] wl12xx: add system_hlid Eliad Peller
2011-08-14 10:17 ` [PATCH v2 17/40] wl12xx: add ROC/CROC commands Eliad Peller
2011-08-14 10:17 ` [PATCH v2 18/40] wl12xx: replace dummy_join with " Eliad Peller
2011-08-14 10:17 ` [PATCH v2 19/40] wl12xx: handle dummy packet event also in ap mode Eliad Peller
2011-08-14 10:17 ` [PATCH v2 20/40] wl12xx: update BT coex configuration params Eliad Peller
2011-08-14 10:17 ` [PATCH v2 21/40] wl12xx: fix session counter Eliad Peller
2011-08-14 10:17 ` [PATCH v2 22/40] wl12xx: use dynamic hlids for AP-mode Eliad Peller
2011-08-14 10:17 ` [PATCH v2 23/40] wl12xx: re-enable block ack session support Eliad Peller
2011-08-14 10:17 ` [PATCH v2 24/40] wl12xx: call wl12xx_cmd_set_peer_state() in AP mode Eliad Peller
2011-08-14 10:17 ` [PATCH v2 25/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
2011-08-14 10:17 ` [PATCH v2 26/40] wl12xx: add wl12xx_cmd_role_start_ibss() Eliad Peller
2011-08-14 10:17 ` [PATCH v2 27/40] wl12xx: support IBSS vif type Eliad Peller
2011-08-14 10:17 ` [PATCH v2 28/40] wl12xx: AP-mode - set STA HT capabilities when adding a STA Eliad Peller
2011-08-14 10:17 ` [PATCH v2 29/40] wl12xx: AP-mode - configure STA HT rates on join Eliad Peller
2011-08-14 10:17 ` [PATCH v2 30/40] wl12xx: AP-mode - configure HT rate support to the FW Eliad Peller
2011-08-14 10:17 ` [PATCH v2 31/40] wl12xx: use ap_bcast_hlid for recorded keys Eliad Peller
2011-08-14 10:17 ` [PATCH v2 32/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
2011-08-14 10:17 ` [PATCH v2 33/40] wl12xx: track freed packets in FW by AC Eliad Peller
2011-08-14 10:17 ` [PATCH v2 34/40] wl12xx: schedule TX packets according to FW packet occupancy Eliad Peller
2011-08-14 10:17 ` [PATCH v2 35/40] wl12xx: handle wrap-around overflow in released Tx blocks FW counter Eliad Peller
2011-08-14 10:17 ` Eliad Peller [this message]
2011-08-14 10:17 ` [PATCH v2 37/40] wl12xx: don't wait for disconnection event Eliad Peller
2011-08-14 10:17 ` [PATCH v2 38/40] wl12xx: set the AP-started flag only after setting keys Eliad Peller
2011-08-14 10:17 ` [PATCH v2 39/40] wl12xx: AP-mode - prevent Tx to stale/invalid stations Eliad Peller
2011-08-14 10:17 ` [PATCH v2 40/40] wl12xx: fix tx_queue_count spurious increment Eliad Peller
2011-08-22 11:11 ` [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Luciano Coelho
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1313317059-16567-37-git-send-email-eliad@wizery.com \
--to=eliad@wizery.com \
--cc=coelho@ti.com \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox