Commit 7d3b29e5 authored by Eliad Peller's avatar Eliad Peller Committed by Kalle Valo

wlcore/wl18xx: handle rc updates in a separate work

sta_rc_update runs in atomic context. thus, a new work
should be scheduled in order to configure the fw
with the required configuration.
Signed-off-by: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 16129d1d
...@@ -1559,26 +1559,19 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, ...@@ -1559,26 +1559,19 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
} }
static void wl18xx_sta_rc_update(struct wl1271 *wl, static void wl18xx_sta_rc_update(struct wl1271 *wl,
struct wl12xx_vif *wlvif, struct wl12xx_vif *wlvif)
struct ieee80211_sta *sta,
u32 changed)
{ {
bool wide = sta->bandwidth >= IEEE80211_STA_RX_BW_40; bool wide = wlvif->rc_update_bw >= IEEE80211_STA_RX_BW_40;
wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide); wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide);
if (!(changed & IEEE80211_RC_BW_CHANGED))
return;
mutex_lock(&wl->mutex);
/* sanity */ /* sanity */
if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS)) if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
goto out; return;
/* ignore the change before association */ /* ignore the change before association */
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
goto out; return;
/* /*
* If we started out as wide, we can change the operation mode. If we * If we started out as wide, we can change the operation mode. If we
...@@ -1589,9 +1582,6 @@ static void wl18xx_sta_rc_update(struct wl1271 *wl, ...@@ -1589,9 +1582,6 @@ static void wl18xx_sta_rc_update(struct wl1271 *wl,
wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide); wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide);
else else
ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif)); ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif));
out:
mutex_unlock(&wl->mutex);
} }
static int wl18xx_set_peer_cap(struct wl1271 *wl, static int wl18xx_set_peer_cap(struct wl1271 *wl,
......
...@@ -211,11 +211,10 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len) ...@@ -211,11 +211,10 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
} }
static inline void static inline void
wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif, wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif)
struct ieee80211_sta *sta, u32 changed)
{ {
if (wl->ops->sta_rc_update) if (wl->ops->sta_rc_update)
wl->ops->sta_rc_update(wl, wlvif, sta, changed); wl->ops->sta_rc_update(wl, wlvif);
} }
static inline int static inline int
......
...@@ -226,6 +226,29 @@ void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl) ...@@ -226,6 +226,29 @@ void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl)
msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout)); msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout));
} }
static void wlcore_rc_update_work(struct work_struct *work)
{
int ret;
struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif,
rc_update_work);
struct wl1271 *wl = wlvif->wl;
mutex_lock(&wl->mutex);
if (unlikely(wl->state != WLCORE_STATE_ON))
goto out;
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
wlcore_hw_sta_rc_update(wl, wlvif);
wl1271_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);
}
static void wl12xx_tx_watchdog_work(struct work_struct *work) static void wl12xx_tx_watchdog_work(struct work_struct *work)
{ {
struct delayed_work *dwork; struct delayed_work *dwork;
...@@ -2279,6 +2302,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) ...@@ -2279,6 +2302,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
wl1271_rx_streaming_enable_work); wl1271_rx_streaming_enable_work);
INIT_WORK(&wlvif->rx_streaming_disable_work, INIT_WORK(&wlvif->rx_streaming_disable_work,
wl1271_rx_streaming_disable_work); wl1271_rx_streaming_disable_work);
INIT_WORK(&wlvif->rc_update_work, wlcore_rc_update_work);
INIT_DELAYED_WORK(&wlvif->channel_switch_work, INIT_DELAYED_WORK(&wlvif->channel_switch_work,
wlcore_channel_switch_work); wlcore_channel_switch_work);
INIT_DELAYED_WORK(&wlvif->connection_loss_work, INIT_DELAYED_WORK(&wlvif->connection_loss_work,
...@@ -2723,6 +2747,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, ...@@ -2723,6 +2747,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
del_timer_sync(&wlvif->rx_streaming_timer); del_timer_sync(&wlvif->rx_streaming_timer);
cancel_work_sync(&wlvif->rx_streaming_enable_work); cancel_work_sync(&wlvif->rx_streaming_enable_work);
cancel_work_sync(&wlvif->rx_streaming_disable_work); cancel_work_sync(&wlvif->rx_streaming_disable_work);
cancel_work_sync(&wlvif->rc_update_work);
cancel_delayed_work_sync(&wlvif->connection_loss_work); cancel_delayed_work_sync(&wlvif->connection_loss_work);
cancel_delayed_work_sync(&wlvif->channel_switch_work); cancel_delayed_work_sync(&wlvif->channel_switch_work);
cancel_delayed_work_sync(&wlvif->pending_auth_complete_work); cancel_delayed_work_sync(&wlvif->pending_auth_complete_work);
...@@ -5370,9 +5395,15 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw, ...@@ -5370,9 +5395,15 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
u32 changed) u32 changed)
{ {
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
struct wl1271 *wl = hw->priv;
wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update");
if (!(changed & IEEE80211_RC_BW_CHANGED))
return;
/* this callback is atomic, so schedule a new work */
wlvif->rc_update_bw = sta->bandwidth;
ieee80211_queue_work(hw, &wlvif->rc_update_work);
} }
static int wlcore_op_get_rssi(struct ieee80211_hw *hw, static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
......
...@@ -106,8 +106,7 @@ struct wlcore_ops { ...@@ -106,8 +106,7 @@ struct wlcore_ops {
struct wl12xx_vif *wlvif, struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch); struct ieee80211_channel_switch *ch_switch);
u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif, void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
struct ieee80211_sta *sta, u32 changed);
int (*set_peer_cap)(struct wl1271 *wl, int (*set_peer_cap)(struct wl1271 *wl,
struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_sta_ht_cap *ht_cap,
bool allow_ht_operation, bool allow_ht_operation,
......
...@@ -463,6 +463,10 @@ struct wl12xx_vif { ...@@ -463,6 +463,10 @@ struct wl12xx_vif {
/* work for canceling ROC after pending auth reply */ /* work for canceling ROC after pending auth reply */
struct delayed_work pending_auth_complete_work; struct delayed_work pending_auth_complete_work;
/* update rate conrol */
enum ieee80211_sta_rx_bandwidth rc_update_bw;
struct work_struct rc_update_work;
/* /*
* total freed FW packets on the link. * total freed FW packets on the link.
* For STA this holds the PN of the link to the AP. * For STA this holds the PN of the link to the AP.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment