Example #1
0
static void iwl_mvm_del_ba(struct iwl_mvm *mvm, int queue,
			   struct iwl_mvm_delba_data *data)
{
	struct iwl_mvm_baid_data *ba_data;
	struct ieee80211_sta *sta;
	struct iwl_mvm_reorder_buffer *reorder_buf;
	u8 baid = data->baid;

	if (WARN_ON_ONCE(baid >= IWL_RX_REORDER_DATA_INVALID_BAID))
		return;

	rcu_read_lock();

	ba_data = rcu_dereference(mvm->baid_map[baid]);
	if (WARN_ON_ONCE(!ba_data))
		goto out;

	sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
	if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
		goto out;

	reorder_buf = &ba_data->reorder_buf[queue];

	/* release all frames that are in the reorder buffer to the stack */
	spin_lock_bh(&reorder_buf->lock);
	iwl_mvm_release_frames(mvm, sta, NULL, reorder_buf,
			       ieee80211_sn_add(reorder_buf->head_sn,
						reorder_buf->buf_size));
	spin_unlock_bh(&reorder_buf->lock);
	del_timer_sync(&reorder_buf->reorder_timer);

out:
	rcu_read_unlock();
}
Example #2
0
void iwl_mvm_reorder_timer_expired(unsigned long data)
{
	struct iwl_mvm_reorder_buffer *buf = (void *)data;
	int i;
	u16 sn = 0, index = 0;
	bool expired = false;

	spin_lock_bh(&buf->lock);

	if (!buf->num_stored || buf->removed) {
		spin_unlock_bh(&buf->lock);
		return;
	}

	for (i = 0; i < buf->buf_size ; i++) {
		index = (buf->head_sn + i) % buf->buf_size;

		if (!skb_peek_tail(&buf->entries[index]))
			continue;
		if (!time_after(jiffies, buf->reorder_time[index] +
				RX_REORDER_BUF_TIMEOUT_MQ))
			break;
		expired = true;
		sn = ieee80211_sn_add(buf->head_sn, i + 1);
	}

	if (expired) {
		struct ieee80211_sta *sta;

		rcu_read_lock();
		sta = rcu_dereference(buf->mvm->fw_id_to_mac_id[buf->sta_id]);
		/* SN is set to the last expired frame + 1 */
		IWL_DEBUG_HT(buf->mvm,
			     "Releasing expired frames for sta %u, sn %d\n",
			     buf->sta_id, sn);
		iwl_mvm_release_frames(buf->mvm, sta, NULL, buf, sn);
		rcu_read_unlock();
	} else if (buf->num_stored) {
		/*
		 * If no frame expired and there are stored frames, index is now
		 * pointing to the first unexpired frame - modify timer
		 * accordingly to this frame.
		 */
		mod_timer(&buf->reorder_timer,
			  buf->reorder_time[index] +
			  1 + RX_REORDER_BUF_TIMEOUT_MQ);
	}
	spin_unlock_bh(&buf->lock);
}