wl12xx: rearm rx streaming per vif
Currently, the rx streaming doesn't support multi-vif (the actual wlvif is taken from wl->vif, and the management is global). Make the rx streaming timers/works per-vif, and pass the the actual vif as param. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
committed by
Luciano Coelho
parent
48e93e402a
commit
9eb599e9c6
@@ -1510,10 +1510,9 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
|
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||||
|
bool enable)
|
||||||
{
|
{
|
||||||
struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
|
|
||||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
|
||||||
struct wl1271_acx_ps_rx_streaming *rx_streaming;
|
struct wl1271_acx_ps_rx_streaming *rx_streaming;
|
||||||
u32 conf_queues, enable_queues;
|
u32 conf_queues, enable_queues;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
@@ -1310,7 +1310,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
|
|||||||
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
|
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
|
||||||
u16 ssn, bool enable, u8 peer_hlid);
|
u16 ssn, bool enable, u8 peer_hlid);
|
||||||
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
|
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
|
||||||
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
|
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||||
|
bool enable);
|
||||||
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||||
int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||||
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
|
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
|
||||||
|
@@ -505,6 +505,7 @@ static ssize_t rx_streaming_interval_write(struct file *file,
|
|||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = file->private_data;
|
struct wl1271 *wl = file->private_data;
|
||||||
|
struct wl12xx_vif *wlvif;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -528,7 +529,9 @@ static ssize_t rx_streaming_interval_write(struct file *file,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
wl1271_recalc_rx_streaming(wl);
|
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||||
|
wl1271_recalc_rx_streaming(wl, wlvif);
|
||||||
|
}
|
||||||
|
|
||||||
wl1271_ps_elp_sleep(wl);
|
wl1271_ps_elp_sleep(wl);
|
||||||
out:
|
out:
|
||||||
@@ -557,6 +560,7 @@ static ssize_t rx_streaming_always_write(struct file *file,
|
|||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = file->private_data;
|
struct wl1271 *wl = file->private_data;
|
||||||
|
struct wl12xx_vif *wlvif;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -580,7 +584,9 @@ static ssize_t rx_streaming_always_write(struct file *file,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
wl1271_recalc_rx_streaming(wl);
|
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||||
|
wl1271_recalc_rx_streaming(wl, wlvif);
|
||||||
|
}
|
||||||
|
|
||||||
wl1271_ps_elp_sleep(wl);
|
wl1271_ps_elp_sleep(wl);
|
||||||
out:
|
out:
|
||||||
|
@@ -220,12 +220,12 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
|
|||||||
}
|
}
|
||||||
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
|
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
|
||||||
} else {
|
} else {
|
||||||
|
clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
|
||||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||||
vif = wl12xx_wlvif_to_vif(wlvif);
|
vif = wl12xx_wlvif_to_vif(wlvif);
|
||||||
ieee80211_enable_dyn_ps(vif);
|
ieee80211_enable_dyn_ps(vif);
|
||||||
|
wl1271_recalc_rx_streaming(wl, wlvif);
|
||||||
}
|
}
|
||||||
clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
|
|
||||||
wl1271_recalc_rx_streaming(wl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -502,12 +502,13 @@ static int wl1271_reg_notify(struct wiphy *wiphy,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable)
|
static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||||
|
bool enable)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* we should hold wl->mutex */
|
/* we should hold wl->mutex */
|
||||||
ret = wl1271_acx_ps_rx_streaming(wl, enable);
|
ret = wl1271_acx_ps_rx_streaming(wl, wlvif, enable);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -523,7 +524,7 @@ out:
|
|||||||
* this function is being called when the rx_streaming interval
|
* this function is being called when the rx_streaming interval
|
||||||
* has beed changed or rx_streaming should be disabled
|
* has beed changed or rx_streaming should be disabled
|
||||||
*/
|
*/
|
||||||
int wl1271_recalc_rx_streaming(struct wl1271 *wl)
|
int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int period = wl->conf.rx_streaming.interval;
|
int period = wl->conf.rx_streaming.interval;
|
||||||
@@ -537,11 +538,11 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl)
|
|||||||
test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
|
test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) &&
|
||||||
(wl->conf.rx_streaming.always ||
|
(wl->conf.rx_streaming.always ||
|
||||||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
|
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)))
|
||||||
ret = wl1271_set_rx_streaming(wl, true);
|
ret = wl1271_set_rx_streaming(wl, wlvif, true);
|
||||||
else {
|
else {
|
||||||
ret = wl1271_set_rx_streaming(wl, false);
|
ret = wl1271_set_rx_streaming(wl, wlvif, false);
|
||||||
/* don't cancel_work_sync since we might deadlock */
|
/* don't cancel_work_sync since we might deadlock */
|
||||||
del_timer_sync(&wl->rx_streaming_timer);
|
del_timer_sync(&wlvif->rx_streaming_timer);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
@@ -550,8 +551,9 @@ out:
|
|||||||
static void wl1271_rx_streaming_enable_work(struct work_struct *work)
|
static void wl1271_rx_streaming_enable_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct wl1271 *wl =
|
struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif,
|
||||||
container_of(work, struct wl1271, rx_streaming_enable_work);
|
rx_streaming_enable_work);
|
||||||
|
struct wl1271 *wl = wlvif->wl;
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
@@ -568,12 +570,12 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = wl1271_set_rx_streaming(wl, true);
|
ret = wl1271_set_rx_streaming(wl, wlvif, true);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_sleep;
|
goto out_sleep;
|
||||||
|
|
||||||
/* stop it after some time of inactivity */
|
/* stop it after some time of inactivity */
|
||||||
mod_timer(&wl->rx_streaming_timer,
|
mod_timer(&wlvif->rx_streaming_timer,
|
||||||
jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));
|
jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration));
|
||||||
|
|
||||||
out_sleep:
|
out_sleep:
|
||||||
@@ -585,8 +587,9 @@ out:
|
|||||||
static void wl1271_rx_streaming_disable_work(struct work_struct *work)
|
static void wl1271_rx_streaming_disable_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct wl1271 *wl =
|
struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif,
|
||||||
container_of(work, struct wl1271, rx_streaming_disable_work);
|
rx_streaming_disable_work);
|
||||||
|
struct wl1271 *wl = wlvif->wl;
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
|
|
||||||
@@ -597,7 +600,7 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = wl1271_set_rx_streaming(wl, false);
|
ret = wl1271_set_rx_streaming(wl, wlvif, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_sleep;
|
goto out_sleep;
|
||||||
|
|
||||||
@@ -609,8 +612,9 @@ out:
|
|||||||
|
|
||||||
static void wl1271_rx_streaming_timer(unsigned long data)
|
static void wl1271_rx_streaming_timer(unsigned long data)
|
||||||
{
|
{
|
||||||
struct wl1271 *wl = (struct wl1271 *)data;
|
struct wl12xx_vif *wlvif = (struct wl12xx_vif *)data;
|
||||||
ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work);
|
struct wl1271 *wl = wlvif->wl;
|
||||||
|
ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wl1271_conf_init(struct wl1271 *wl)
|
static void wl1271_conf_init(struct wl1271 *wl)
|
||||||
@@ -1827,9 +1831,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
|
|||||||
cancel_delayed_work_sync(&wl->scan_complete_work);
|
cancel_delayed_work_sync(&wl->scan_complete_work);
|
||||||
cancel_work_sync(&wl->netstack_work);
|
cancel_work_sync(&wl->netstack_work);
|
||||||
cancel_work_sync(&wl->tx_work);
|
cancel_work_sync(&wl->tx_work);
|
||||||
del_timer_sync(&wl->rx_streaming_timer);
|
|
||||||
cancel_work_sync(&wl->rx_streaming_enable_work);
|
|
||||||
cancel_work_sync(&wl->rx_streaming_disable_work);
|
|
||||||
cancel_delayed_work_sync(&wl->elp_work);
|
cancel_delayed_work_sync(&wl->elp_work);
|
||||||
|
|
||||||
/* let's notify MAC80211 about the remaining pending TX frames */
|
/* let's notify MAC80211 about the remaining pending TX frames */
|
||||||
@@ -1960,9 +1961,16 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
|
|||||||
wlvif->rate_set = CONF_TX_RATE_MASK_BASIC;
|
wlvif->rate_set = CONF_TX_RATE_MASK_BASIC;
|
||||||
wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT;
|
wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT;
|
||||||
|
|
||||||
|
INIT_WORK(&wlvif->rx_streaming_enable_work,
|
||||||
|
wl1271_rx_streaming_enable_work);
|
||||||
|
INIT_WORK(&wlvif->rx_streaming_disable_work,
|
||||||
|
wl1271_rx_streaming_disable_work);
|
||||||
INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work);
|
INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work);
|
||||||
INIT_LIST_HEAD(&wlvif->list);
|
INIT_LIST_HEAD(&wlvif->list);
|
||||||
|
|
||||||
|
setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer,
|
||||||
|
(unsigned long) wlvif);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2203,6 +2211,9 @@ deinit:
|
|||||||
wl->sta_count--;
|
wl->sta_count--;
|
||||||
|
|
||||||
mutex_unlock(&wl->mutex);
|
mutex_unlock(&wl->mutex);
|
||||||
|
del_timer_sync(&wlvif->rx_streaming_timer);
|
||||||
|
cancel_work_sync(&wlvif->rx_streaming_enable_work);
|
||||||
|
cancel_work_sync(&wlvif->rx_streaming_disable_work);
|
||||||
cancel_delayed_work_sync(&wlvif->pspoll_work);
|
cancel_delayed_work_sync(&wlvif->pspoll_work);
|
||||||
|
|
||||||
mutex_lock(&wl->mutex);
|
mutex_lock(&wl->mutex);
|
||||||
@@ -4903,10 +4914,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
|
|||||||
INIT_WORK(&wl->tx_work, wl1271_tx_work);
|
INIT_WORK(&wl->tx_work, wl1271_tx_work);
|
||||||
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
|
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
|
||||||
INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
|
INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
|
||||||
INIT_WORK(&wl->rx_streaming_enable_work,
|
|
||||||
wl1271_rx_streaming_enable_work);
|
|
||||||
INIT_WORK(&wl->rx_streaming_disable_work,
|
|
||||||
wl1271_rx_streaming_disable_work);
|
|
||||||
|
|
||||||
wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
|
wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
|
||||||
if (!wl->freezable_wq) {
|
if (!wl->freezable_wq) {
|
||||||
@@ -4930,8 +4937,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
|
|||||||
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
|
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
|
||||||
wl->system_hlid = WL12XX_SYSTEM_HLID;
|
wl->system_hlid = WL12XX_SYSTEM_HLID;
|
||||||
wl->active_sta_count = 0;
|
wl->active_sta_count = 0;
|
||||||
setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
|
|
||||||
(unsigned long) wl);
|
|
||||||
wl->fwlog_size = 0;
|
wl->fwlog_size = 0;
|
||||||
init_waitqueue_head(&wl->fwlog_waitq);
|
init_waitqueue_head(&wl->fwlog_waitq);
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "acx.h"
|
#include "acx.h"
|
||||||
#include "reg.h"
|
#include "reg.h"
|
||||||
#include "rx.h"
|
#include "rx.h"
|
||||||
|
#include "tx.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
|
static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
|
||||||
@@ -96,7 +97,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
||||||
bool unaligned)
|
bool unaligned, u8 *hlid)
|
||||||
{
|
{
|
||||||
struct wl1271_rx_descriptor *desc;
|
struct wl1271_rx_descriptor *desc;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
@@ -159,6 +160,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
|||||||
* payload aligned to 4 bytes.
|
* payload aligned to 4 bytes.
|
||||||
*/
|
*/
|
||||||
memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
|
memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
|
||||||
|
*hlid = desc->hlid;
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
if (ieee80211_is_beacon(hdr->frame_control))
|
if (ieee80211_is_beacon(hdr->frame_control))
|
||||||
@@ -169,10 +171,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
|||||||
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
|
wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
|
||||||
|
|
||||||
seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
|
||||||
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb,
|
wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb,
|
||||||
skb->len - desc->pad_len,
|
skb->len - desc->pad_len,
|
||||||
beacon ? "beacon" : "",
|
beacon ? "beacon" : "",
|
||||||
seq_num);
|
seq_num, *hlid);
|
||||||
|
|
||||||
skb_trim(skb, skb->len - desc->pad_len);
|
skb_trim(skb, skb->len - desc->pad_len);
|
||||||
|
|
||||||
@@ -185,8 +187,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
|||||||
void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
|
void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
|
||||||
{
|
{
|
||||||
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
|
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
|
||||||
struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */
|
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
|
||||||
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
|
|
||||||
u32 buf_size;
|
u32 buf_size;
|
||||||
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||||
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||||
@@ -194,8 +195,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
|
|||||||
u32 mem_block;
|
u32 mem_block;
|
||||||
u32 pkt_length;
|
u32 pkt_length;
|
||||||
u32 pkt_offset;
|
u32 pkt_offset;
|
||||||
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
|
u8 hlid;
|
||||||
bool had_data = false;
|
|
||||||
bool unaligned = false;
|
bool unaligned = false;
|
||||||
|
|
||||||
while (drv_rx_counter != fw_rx_counter) {
|
while (drv_rx_counter != fw_rx_counter) {
|
||||||
@@ -255,8 +255,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
|
|||||||
*/
|
*/
|
||||||
if (wl1271_rx_handle_data(wl,
|
if (wl1271_rx_handle_data(wl,
|
||||||
wl->aggr_buf + pkt_offset,
|
wl->aggr_buf + pkt_offset,
|
||||||
pkt_length, unaligned) == 1)
|
pkt_length, unaligned,
|
||||||
had_data = true;
|
&hlid) == 1) {
|
||||||
|
WARN_ON(hlid >= WL12XX_MAX_LINKS);
|
||||||
|
__set_bit(hlid, active_hlids);
|
||||||
|
}
|
||||||
|
|
||||||
wl->rx_counter++;
|
wl->rx_counter++;
|
||||||
drv_rx_counter++;
|
drv_rx_counter++;
|
||||||
@@ -272,17 +275,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
|
|||||||
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
|
if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
|
||||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||||
|
|
||||||
if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
|
wl12xx_rearm_rx_streaming(wl, active_hlids);
|
||||||
(wl->conf.rx_streaming.always ||
|
|
||||||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
|
|
||||||
u32 timeout = wl->conf.rx_streaming.duration;
|
|
||||||
|
|
||||||
/* restart rx streaming */
|
|
||||||
if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
|
|
||||||
ieee80211_queue_work(wl->hw,
|
|
||||||
&wl->rx_streaming_enable_work);
|
|
||||||
|
|
||||||
mod_timer(&wl->rx_streaming_timer,
|
|
||||||
jiffies + msecs_to_jiffies(timeout));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -643,21 +643,58 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb)
|
|||||||
return ieee80211_is_data_present(hdr->frame_control);
|
return ieee80211_is_data_present(hdr->frame_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
|
||||||
|
{
|
||||||
|
struct wl12xx_vif *wlvif;
|
||||||
|
u32 timeout;
|
||||||
|
u8 hlid;
|
||||||
|
|
||||||
|
if (!wl->conf.rx_streaming.interval)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!wl->conf.rx_streaming.always &&
|
||||||
|
!test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
timeout = wl->conf.rx_streaming.duration;
|
||||||
|
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||||
|
bool found = false;
|
||||||
|
for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) {
|
||||||
|
if (test_bit(hlid, wlvif->links_map)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* enable rx streaming */
|
||||||
|
if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
|
||||||
|
ieee80211_queue_work(wl->hw,
|
||||||
|
&wlvif->rx_streaming_enable_work);
|
||||||
|
|
||||||
|
mod_timer(&wlvif->rx_streaming_timer,
|
||||||
|
jiffies + msecs_to_jiffies(timeout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wl1271_tx_work_locked(struct wl1271 *wl)
|
void wl1271_tx_work_locked(struct wl1271 *wl)
|
||||||
{
|
{
|
||||||
struct wl12xx_vif *wlvif;
|
struct wl12xx_vif *wlvif;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
struct wl1271_tx_hw_descr *desc;
|
||||||
u32 buf_offset = 0;
|
u32 buf_offset = 0;
|
||||||
bool sent_packets = false;
|
bool sent_packets = false;
|
||||||
bool had_data = false;
|
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
|
||||||
/* TODO: save bitmap of relevant stations */
|
|
||||||
bool is_sta = false;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ((skb = wl1271_skb_dequeue(wl))) {
|
while ((skb = wl1271_skb_dequeue(wl))) {
|
||||||
|
bool has_data = false;
|
||||||
|
|
||||||
wlvif = NULL;
|
wlvif = NULL;
|
||||||
if (!wl12xx_is_dummy_packet(wl, skb)) {
|
if (!wl12xx_is_dummy_packet(wl, skb)) {
|
||||||
struct ieee80211_tx_info *info;
|
struct ieee80211_tx_info *info;
|
||||||
@@ -667,9 +704,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
|||||||
vif = info->control.vif;
|
vif = info->control.vif;
|
||||||
wlvif = wl12xx_vif_to_data(vif);
|
wlvif = wl12xx_vif_to_data(vif);
|
||||||
}
|
}
|
||||||
|
has_data = wlvif && wl1271_tx_is_data_present(skb);
|
||||||
if (wl1271_tx_is_data_present(skb))
|
|
||||||
had_data = true;
|
|
||||||
|
|
||||||
ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
|
ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset);
|
||||||
if (ret == -EAGAIN) {
|
if (ret == -EAGAIN) {
|
||||||
@@ -698,8 +733,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
|||||||
}
|
}
|
||||||
buf_offset += ret;
|
buf_offset += ret;
|
||||||
wl->tx_packets_count++;
|
wl->tx_packets_count++;
|
||||||
if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS)
|
if (has_data) {
|
||||||
is_sta = true;
|
desc = (struct wl1271_tx_hw_descr *) skb->data;
|
||||||
|
__set_bit(desc->hlid, active_hlids);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out_ack:
|
out_ack:
|
||||||
@@ -719,19 +756,7 @@ out_ack:
|
|||||||
|
|
||||||
wl1271_handle_tx_low_watermark(wl);
|
wl1271_handle_tx_low_watermark(wl);
|
||||||
}
|
}
|
||||||
if (is_sta && wl->conf.rx_streaming.interval && had_data &&
|
wl12xx_rearm_rx_streaming(wl, active_hlids);
|
||||||
(wl->conf.rx_streaming.always ||
|
|
||||||
test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
|
|
||||||
u32 timeout = wl->conf.rx_streaming.duration;
|
|
||||||
|
|
||||||
/* enable rx streaming */
|
|
||||||
if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
|
|
||||||
ieee80211_queue_work(wl->hw,
|
|
||||||
&wl->rx_streaming_enable_work);
|
|
||||||
|
|
||||||
mod_timer(&wl->rx_streaming_timer,
|
|
||||||
jiffies + msecs_to_jiffies(timeout));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wl1271_tx_work(struct work_struct *work)
|
void wl1271_tx_work(struct work_struct *work)
|
||||||
|
@@ -220,6 +220,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||||||
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
|
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
|
||||||
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
|
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
|
||||||
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
|
bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
|
||||||
|
void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids);
|
||||||
|
|
||||||
/* from main.c */
|
/* from main.c */
|
||||||
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
|
void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
|
||||||
|
@@ -480,11 +480,6 @@ struct wl1271 {
|
|||||||
/* The current band */
|
/* The current band */
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
|
|
||||||
/* Rx Streaming */
|
|
||||||
struct work_struct rx_streaming_enable_work;
|
|
||||||
struct work_struct rx_streaming_disable_work;
|
|
||||||
struct timer_list rx_streaming_timer;
|
|
||||||
|
|
||||||
struct completion *elp_compl;
|
struct completion *elp_compl;
|
||||||
struct delayed_work elp_work;
|
struct delayed_work elp_work;
|
||||||
|
|
||||||
@@ -635,6 +630,11 @@ struct wl12xx_vif {
|
|||||||
bool ba_support;
|
bool ba_support;
|
||||||
bool ba_allowed;
|
bool ba_allowed;
|
||||||
|
|
||||||
|
/* Rx Streaming */
|
||||||
|
struct work_struct rx_streaming_enable_work;
|
||||||
|
struct work_struct rx_streaming_disable_work;
|
||||||
|
struct timer_list rx_streaming_timer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct must be last!
|
* This struct must be last!
|
||||||
* data that has to be saved acrossed reconfigs (e.g. recovery)
|
* data that has to be saved acrossed reconfigs (e.g. recovery)
|
||||||
@@ -681,7 +681,7 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif)
|
|||||||
|
|
||||||
int wl1271_plt_start(struct wl1271 *wl);
|
int wl1271_plt_start(struct wl1271 *wl);
|
||||||
int wl1271_plt_stop(struct wl1271 *wl);
|
int wl1271_plt_stop(struct wl1271 *wl);
|
||||||
int wl1271_recalc_rx_streaming(struct wl1271 *wl);
|
int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||||
void wl12xx_queue_recovery_work(struct wl1271 *wl);
|
void wl12xx_queue_recovery_work(struct wl1271 *wl);
|
||||||
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
|
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user