Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+4 −14
Original line number Diff line number Diff line
@@ -1559,26 +1559,19 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
}

static void wl18xx_sta_rc_update(struct wl1271 *wl,
				 struct wl12xx_vif *wlvif,
				 struct ieee80211_sta *sta,
				 u32 changed)
				 struct wl12xx_vif *wlvif)
{
	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);

	if (!(changed & IEEE80211_RC_BW_CHANGED))
		return;

	mutex_lock(&wl->mutex);

	/* sanity */
	if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
		goto out;
		return;

	/* ignore the change before association */
	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
@@ -1589,9 +1582,6 @@ static void wl18xx_sta_rc_update(struct wl1271 *wl,
		wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide);
	else
		ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif));

out:
	mutex_unlock(&wl->mutex);
}

static int wl18xx_set_peer_cap(struct wl1271 *wl,
+2 −3
Original line number Diff line number Diff line
@@ -211,11 +211,10 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
}

static inline void
wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif,
			struct ieee80211_sta *sta, u32 changed)
wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
	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
+33 −2
Original line number Diff line number Diff line
@@ -226,6 +226,29 @@ void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl)
		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)
{
	struct delayed_work *dwork;
@@ -2279,6 +2302,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
		  wl1271_rx_streaming_enable_work);
	INIT_WORK(&wlvif->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,
			  wlcore_channel_switch_work);
	INIT_DELAYED_WORK(&wlvif->connection_loss_work,
@@ -2723,6 +2747,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
	del_timer_sync(&wlvif->rx_streaming_timer);
	cancel_work_sync(&wlvif->rx_streaming_enable_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->channel_switch_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,
				    u32 changed)
{
	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,
+1 −2
Original line number Diff line number Diff line
@@ -106,8 +106,7 @@ struct wlcore_ops {
			      struct wl12xx_vif *wlvif,
			      struct ieee80211_channel_switch *ch_switch);
	u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
	void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
			      struct ieee80211_sta *sta, u32 changed);
	void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
	int (*set_peer_cap)(struct wl1271 *wl,
			    struct ieee80211_sta_ht_cap *ht_cap,
			    bool allow_ht_operation,
+4 −0
Original line number Diff line number Diff line
@@ -463,6 +463,10 @@ struct wl12xx_vif {
	/* work for canceling ROC after pending auth reply */
	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.
	 * For STA this holds the PN of the link to the AP.