net/mac80211/ht.c

Source file repositories/reference/linux-study-clean/net/mac80211/ht.c

File Facts

System
Linux kernel
Corpus path
net/mac80211/ht.c
Extension
.c
Size
18270 bytes
Lines
615
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!blocked && tid_tx) {
			struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
			struct ieee80211_sub_if_data *sdata =
				vif_to_sdata(txqi->txq.vif);
			struct fq *fq = &sdata->local->fq;

			spin_lock_bh(&fq->lock);

			/* Allow only frags to be dequeued */
			set_bit(IEEE80211_TXQ_STOP, &txqi->flags);

			if (!skb_queue_empty(&txqi->frags)) {
				/* Fragmented Tx is ongoing, wait for it to
				 * finish. Reschedule worker to retry later.
				 */

				spin_unlock_bh(&fq->lock);
				spin_unlock_bh(&sta->lock);

				/* Give the task working on the txq a chance
				 * to send out the queued frags
				 */
				synchronize_net();

				wiphy_work_queue(sdata->local->hw.wiphy, work);
				return;
			}

			spin_unlock_bh(&fq->lock);

			/*
			 * Assign it over to the normal tid_tx array
			 * where it "goes live".
			 */

			sta->ampdu_mlme.tid_start_tx[tid] = NULL;
			/* could there be a race? */
			if (sta->ampdu_mlme.tid_tx[tid])
				kfree(tid_tx);
			else
				ieee80211_assign_tid_tx(sta, tid, tid_tx);
			spin_unlock_bh(&sta->lock);

			ieee80211_tx_ba_session_handle_start(sta, tid);
			continue;
		}
		spin_unlock_bh(&sta->lock);

		tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
		if (!tid_tx)
			continue;

		if (!blocked &&
		    test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state))
			ieee80211_start_tx_ba_cb(sta, tid, tid_tx);
		if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state))
			__ieee80211_stop_tx_ba_session(sta, tid,
						       AGG_STOP_LOCAL_REQUEST);
		if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
			ieee80211_stop_tx_ba_cb(sta, tid, tid_tx);
	}
}

void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
			  const u8 *da, u16 tid,
			  u16 initiator, u16 reason_code,
			  bool use_ndp)
{
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
	u16 params;

	skb = dev_alloc_skb(IEEE80211_MIN_ACTION_SIZE(delba) +
			    local->hw.extra_tx_headroom);
	if (!skb)
		return;

	skb_reserve(skb, local->hw.extra_tx_headroom);
	mgmt = ieee80211_mgmt_ba(skb, da, sdata);

	skb_put(skb, 2 + sizeof(mgmt->u.action.delba));

	mgmt->u.action.category = WLAN_CATEGORY_BACK;
	mgmt->u.action.action_code = use_ndp ?
		WLAN_ACTION_NDP_DELBA : WLAN_ACTION_DELBA;
	params = (u16)(initiator << 11); 	/* bit 11 initiator */
	params |= (u16)(tid << 12); 		/* bit 15:12 TID number */

	mgmt->u.action.delba.params = cpu_to_le16(params);

Annotation

Implementation Notes