diff options
author | Eliad Peller <eliad@wizery.com> | 2014-12-29 01:24:03 -0500 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2015-01-09 08:47:52 -0500 |
commit | 7d3b29e5c86e0da38052d33fdd1f195d4591c6b2 (patch) | |
tree | 7449e1c4ced2087e4fab31d9fd3d88374cf21f73 /drivers/net/wireless/ti | |
parent | 16129d1d59be0f330f80b33fef8a7a7d7b18394d (diff) |
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: Eliad Peller <eliad@wizery.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/hw_ops.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore_i.h | 4 |
5 files changed, 44 insertions, 21 deletions
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 8e562610bf16..96dbe71662c1 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -1559,26 +1559,19 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, | |||
1559 | } | 1559 | } |
1560 | 1560 | ||
1561 | static void wl18xx_sta_rc_update(struct wl1271 *wl, | 1561 | static void wl18xx_sta_rc_update(struct wl1271 *wl, |
1562 | struct wl12xx_vif *wlvif, | 1562 | struct wl12xx_vif *wlvif) |
1563 | struct ieee80211_sta *sta, | ||
1564 | u32 changed) | ||
1565 | { | 1563 | { |
1566 | bool wide = sta->bandwidth >= IEEE80211_STA_RX_BW_40; | 1564 | bool wide = wlvif->rc_update_bw >= IEEE80211_STA_RX_BW_40; |
1567 | 1565 | ||
1568 | wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide); | 1566 | wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide); |
1569 | 1567 | ||
1570 | if (!(changed & IEEE80211_RC_BW_CHANGED)) | ||
1571 | return; | ||
1572 | |||
1573 | mutex_lock(&wl->mutex); | ||
1574 | |||
1575 | /* sanity */ | 1568 | /* sanity */ |
1576 | if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS)) | 1569 | if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS)) |
1577 | goto out; | 1570 | return; |
1578 | 1571 | ||
1579 | /* ignore the change before association */ | 1572 | /* ignore the change before association */ |
1580 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | 1573 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
1581 | goto out; | 1574 | return; |
1582 | 1575 | ||
1583 | /* | 1576 | /* |
1584 | * If we started out as wide, we can change the operation mode. If we | 1577 | * 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 | wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide); | 1582 | wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide); |
1590 | else | 1583 | else |
1591 | ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif)); | 1584 | ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif)); |
1592 | |||
1593 | out: | ||
1594 | mutex_unlock(&wl->mutex); | ||
1595 | } | 1585 | } |
1596 | 1586 | ||
1597 | static int wl18xx_set_peer_cap(struct wl1271 *wl, | 1587 | static int wl18xx_set_peer_cap(struct wl1271 *wl, |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index aa9f82c72296..29ce55ff8823 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -211,11 +211,10 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len) | |||
211 | } | 211 | } |
212 | 212 | ||
213 | static inline void | 213 | static inline void |
214 | wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 214 | wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
215 | struct ieee80211_sta *sta, u32 changed) | ||
216 | { | 215 | { |
217 | if (wl->ops->sta_rc_update) | 216 | if (wl->ops->sta_rc_update) |
218 | wl->ops->sta_rc_update(wl, wlvif, sta, changed); | 217 | wl->ops->sta_rc_update(wl, wlvif); |
219 | } | 218 | } |
220 | 219 | ||
221 | static inline int | 220 | static inline int |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 6ad3fcedab9b..7b32b4536fff 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -226,6 +226,29 @@ void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl) | |||
226 | msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout)); | 226 | msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout)); |
227 | } | 227 | } |
228 | 228 | ||
229 | static void wlcore_rc_update_work(struct work_struct *work) | ||
230 | { | ||
231 | int ret; | ||
232 | struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, | ||
233 | rc_update_work); | ||
234 | struct wl1271 *wl = wlvif->wl; | ||
235 | |||
236 | mutex_lock(&wl->mutex); | ||
237 | |||
238 | if (unlikely(wl->state != WLCORE_STATE_ON)) | ||
239 | goto out; | ||
240 | |||
241 | ret = wl1271_ps_elp_wakeup(wl); | ||
242 | if (ret < 0) | ||
243 | goto out; | ||
244 | |||
245 | wlcore_hw_sta_rc_update(wl, wlvif); | ||
246 | |||
247 | wl1271_ps_elp_sleep(wl); | ||
248 | out: | ||
249 | mutex_unlock(&wl->mutex); | ||
250 | } | ||
251 | |||
229 | static void wl12xx_tx_watchdog_work(struct work_struct *work) | 252 | static void wl12xx_tx_watchdog_work(struct work_struct *work) |
230 | { | 253 | { |
231 | struct delayed_work *dwork; | 254 | struct delayed_work *dwork; |
@@ -2279,6 +2302,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
2279 | wl1271_rx_streaming_enable_work); | 2302 | wl1271_rx_streaming_enable_work); |
2280 | INIT_WORK(&wlvif->rx_streaming_disable_work, | 2303 | INIT_WORK(&wlvif->rx_streaming_disable_work, |
2281 | wl1271_rx_streaming_disable_work); | 2304 | wl1271_rx_streaming_disable_work); |
2305 | INIT_WORK(&wlvif->rc_update_work, wlcore_rc_update_work); | ||
2282 | INIT_DELAYED_WORK(&wlvif->channel_switch_work, | 2306 | INIT_DELAYED_WORK(&wlvif->channel_switch_work, |
2283 | wlcore_channel_switch_work); | 2307 | wlcore_channel_switch_work); |
2284 | INIT_DELAYED_WORK(&wlvif->connection_loss_work, | 2308 | INIT_DELAYED_WORK(&wlvif->connection_loss_work, |
@@ -2723,6 +2747,7 @@ unlock: | |||
2723 | del_timer_sync(&wlvif->rx_streaming_timer); | 2747 | del_timer_sync(&wlvif->rx_streaming_timer); |
2724 | cancel_work_sync(&wlvif->rx_streaming_enable_work); | 2748 | cancel_work_sync(&wlvif->rx_streaming_enable_work); |
2725 | cancel_work_sync(&wlvif->rx_streaming_disable_work); | 2749 | cancel_work_sync(&wlvif->rx_streaming_disable_work); |
2750 | cancel_work_sync(&wlvif->rc_update_work); | ||
2726 | cancel_delayed_work_sync(&wlvif->connection_loss_work); | 2751 | cancel_delayed_work_sync(&wlvif->connection_loss_work); |
2727 | cancel_delayed_work_sync(&wlvif->channel_switch_work); | 2752 | cancel_delayed_work_sync(&wlvif->channel_switch_work); |
2728 | cancel_delayed_work_sync(&wlvif->pending_auth_complete_work); | 2753 | 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 | u32 changed) | 5395 | u32 changed) |
5371 | { | 5396 | { |
5372 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 5397 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
5373 | struct wl1271 *wl = hw->priv; | ||
5374 | 5398 | ||
5375 | wlcore_hw_sta_rc_update(wl, wlvif, sta, changed); | 5399 | wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update"); |
5400 | |||
5401 | if (!(changed & IEEE80211_RC_BW_CHANGED)) | ||
5402 | return; | ||
5403 | |||
5404 | /* this callback is atomic, so schedule a new work */ | ||
5405 | wlvif->rc_update_bw = sta->bandwidth; | ||
5406 | ieee80211_queue_work(hw, &wlvif->rc_update_work); | ||
5376 | } | 5407 | } |
5377 | 5408 | ||
5378 | static int wlcore_op_get_rssi(struct ieee80211_hw *hw, | 5409 | static int wlcore_op_get_rssi(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index df78cf12ef15..2440ebe8a8d6 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -106,8 +106,7 @@ struct wlcore_ops { | |||
106 | struct wl12xx_vif *wlvif, | 106 | struct wl12xx_vif *wlvif, |
107 | struct ieee80211_channel_switch *ch_switch); | 107 | struct ieee80211_channel_switch *ch_switch); |
108 | u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); | 108 | u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); |
109 | void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif, | 109 | void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
110 | struct ieee80211_sta *sta, u32 changed); | ||
111 | int (*set_peer_cap)(struct wl1271 *wl, | 110 | int (*set_peer_cap)(struct wl1271 *wl, |
112 | struct ieee80211_sta_ht_cap *ht_cap, | 111 | struct ieee80211_sta_ht_cap *ht_cap, |
113 | bool allow_ht_operation, | 112 | bool allow_ht_operation, |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 0e52556044d9..811851d00b33 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -463,6 +463,10 @@ struct wl12xx_vif { | |||
463 | /* work for canceling ROC after pending auth reply */ | 463 | /* work for canceling ROC after pending auth reply */ |
464 | struct delayed_work pending_auth_complete_work; | 464 | struct delayed_work pending_auth_complete_work; |
465 | 465 | ||
466 | /* update rate conrol */ | ||
467 | enum ieee80211_sta_rx_bandwidth rc_update_bw; | ||
468 | struct work_struct rc_update_work; | ||
469 | |||
466 | /* | 470 | /* |
467 | * total freed FW packets on the link. | 471 | * total freed FW packets on the link. |
468 | * For STA this holds the PN of the link to the AP. | 472 | * For STA this holds the PN of the link to the AP. |