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

Commit e755f882 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

iwlwifi: redesign PASSIVE_NO_RX workaround



The PASSIVE_NO_RX workaround currently crosses
through the op_mode and transport layers, which
is a bit odd. This also isn't necessary, if the
transport simply reports when queues are full
(or no longer full) the op_mode can keep track
of this state, and report to mac80211 only what
*it* thinks is appropriate. What is appropriate
can then be based on whether queues should be
stopped to wait for RX or not.

This significantly simplifies the transport API,
it no longer needs to expose anything to stop a
queue, nor to wake "any" queue, this can all be
handled in the upper layer completely.

Also simplify the handling to not be dependent
on the context, that makes little sense as the
queues are shared and both contexts have to be
on the same channel anyway.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ea886a60
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -807,16 +807,12 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
	* sometimes even after already having transmitted frames for the
	* association because the new RXON may reset the information.
	*/
	if (unlikely(ieee80211_is_beacon(fc))) {
	if (unlikely(ieee80211_is_beacon(fc) && priv->passive_no_rx)) {
		for_each_context(priv, ctx) {
			if (!ctx->last_tx_rejected)
				continue;
			if (compare_ether_addr(hdr->addr3,
					       ctx->active.bssid_addr))
				continue;
			ctx->last_tx_rejected = false;
			iwl_trans_wake_any_queue(trans(priv), ctx->ctxid,
				"channel got active");
			iwlagn_lift_passive_no_rx(priv);
		}
	}

+2 −6
Original line number Diff line number Diff line
@@ -833,12 +833,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
			 * not get stuck in this case either since it
			 * can happen if userspace gets confused.
			 */
			if (ctx->last_tx_rejected) {
				ctx->last_tx_rejected = false;
				iwl_trans_wake_any_queue(trans(priv),
							 ctx->ctxid,
							 "Disassoc: flush queue");
			}
			iwlagn_lift_passive_no_rx(priv);

			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;

			if (ctx->ctxid == IWL_RXON_CTX_BSS)
+6 −6
Original line number Diff line number Diff line
@@ -1064,8 +1064,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
		}

		/*we can free until ssn % q.n_bd not inclusive */
		WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
				  ssn, status, &skbs));
		WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid,
					  txq_id, ssn, &skbs));
		iwlagn_check_ratid_empty(priv, sta_id, tid);
		freed = 0;

@@ -1086,9 +1086,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
			if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
			    iwl_is_associated_ctx(ctx) && ctx->vif &&
			    ctx->vif->type == NL80211_IFTYPE_STATION) {
				ctx->last_tx_rejected = true;
				iwl_trans_stop_queue(trans(priv), txq_id,
					"Tx on passive channel");
				/* block and stop all queues */
				priv->passive_no_rx = true;
				ieee80211_stop_queues(priv->hw);

				IWL_DEBUG_TX_REPLY(priv,
					   "TXQ %d status %s (0x%08x) "
@@ -1182,7 +1182,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
	 * block-ack window (we assume that they've been successfully
	 * transmitted ... if not, it's too late anyway). */
	if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
			      ba_resp_scd_ssn, 0, &reclaimed_skbs)) {
			      ba_resp_scd_ssn, &reclaimed_skbs)) {
		spin_unlock(&priv->sta_lock);
		return 0;
	}
+33 −0
Original line number Diff line number Diff line
@@ -1427,6 +1427,39 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
	cfg(priv)->lib->nic_config(priv);
}

static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
{
	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);

	set_bit(ac, &priv->transport_queue_stop);
	ieee80211_stop_queue(priv->hw, ac);
}

static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
{
	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);

	clear_bit(ac, &priv->transport_queue_stop);

	if (!priv->passive_no_rx)
		ieee80211_wake_queue(priv->hw, ac);
}

void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
{
	int ac;

	if (!priv->passive_no_rx)
		return;

	for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
		if (!test_bit(ac, &priv->transport_queue_stop))
			ieee80211_wake_queue(priv->hw, ac);
	}

	priv->passive_no_rx = false;
}

const struct iwl_op_mode_ops iwl_dvm_ops = {
	.start = iwl_op_mode_dvm_start,
	.stop = iwl_op_mode_dvm_stop,
+2 −3
Original line number Diff line number Diff line
@@ -84,14 +84,13 @@ void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode,
				 struct iwl_rx_cmd_buffer *rxb,
				 struct iwl_device_cmd *cmd);
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
void iwl_nic_error(struct iwl_op_mode *op_mode);

bool iwl_check_for_ct_kill(struct iwl_priv *priv);

void iwlagn_lift_passive_no_rx(struct iwl_priv *priv);

/* MAC80211 */
struct ieee80211_hw *iwl_alloc_all(void);
int iwlagn_mac_setup_register(struct iwl_priv *priv,
Loading