drivers/net/wireless/intel/iwlwifi/mld/agg.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/mld/agg.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/agg.c
Extension
.c
Size
20028 bytes
Lines
687
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

while ((skb = __skb_dequeue(skb_list))) {
			iwl_mld_pass_packet_to_mac80211(mld, napi, skb,
							reorder_buf->queue,
							sta);
			reorder_buf->num_stored--;
		}
	}
	reorder_buf->head_sn = nssn;
}

static void iwl_mld_release_frames_from_notif(struct iwl_mld *mld,
					      struct napi_struct *napi,
					      u8 baid, u16 nssn, int queue)
{
	struct iwl_mld_reorder_buffer *reorder_buf;
	struct iwl_mld_baid_data *ba_data;
	struct ieee80211_link_sta *link_sta;
	u32 sta_id;

	IWL_DEBUG_HT(mld, "Frame release notification for BAID %u, NSSN %d\n",
		     baid, nssn);

	if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
			 baid >= ARRAY_SIZE(mld->fw_id_to_ba)))
		return;

	rcu_read_lock();

	ba_data = rcu_dereference(mld->fw_id_to_ba[baid]);
	if (!ba_data) {
		IWL_DEBUG_HT(mld, "BAID %d not found in map\n", baid);
		goto out_unlock;
	}

	/* pick any STA ID to find the pointer */
	if (WARN_ON_ONCE(!ba_data->sta_mask))
		goto out_unlock;

	sta_id = ffs(ba_data->sta_mask) - 1;
	link_sta = rcu_dereference(mld->fw_id_to_link_sta[sta_id]);
	if (WARN_ON_ONCE(IS_ERR_OR_NULL(link_sta) || !link_sta->sta))
		goto out_unlock;

	reorder_buf = &ba_data->reorder_buf[queue];

	iwl_mld_reorder_release_frames(mld, link_sta->sta, napi, ba_data,
				       reorder_buf, nssn);
out_unlock:
	rcu_read_unlock();
}

void iwl_mld_handle_frame_release_notif(struct iwl_mld *mld,
					struct napi_struct *napi,
					struct iwl_rx_packet *pkt, int queue)
{
	struct iwl_frame_release *release = (void *)pkt->data;
	u32 pkt_len = iwl_rx_packet_payload_len(pkt);

	if (IWL_FW_CHECK(mld, pkt_len < sizeof(*release),
			 "Unexpected frame release notif size %u (expected %zu)\n",
			 pkt_len, sizeof(*release)))
		return;

	iwl_mld_release_frames_from_notif(mld, napi, release->baid,
					  le16_to_cpu(release->nssn),
					  queue);
}

void iwl_mld_handle_bar_frame_release_notif(struct iwl_mld *mld,
					    struct napi_struct *napi,
					    struct iwl_rx_packet *pkt,
					    int queue)
{
	struct iwl_bar_frame_release *release = (void *)pkt->data;
	struct iwl_mld_baid_data *baid_data;
	unsigned int baid, nssn, sta_id, tid;
	u32 pkt_len = iwl_rx_packet_payload_len(pkt);

	if (IWL_FW_CHECK(mld, pkt_len < sizeof(*release),
			 "Unexpected frame release notif size %u (expected %zu)\n",
			 pkt_len, sizeof(*release)))
		return;

	baid = le32_get_bits(release->ba_info,
			     IWL_BAR_FRAME_RELEASE_BAID_MASK);
	nssn = le32_get_bits(release->ba_info,
			     IWL_BAR_FRAME_RELEASE_NSSN_MASK);
	sta_id = le32_get_bits(release->sta_tid,
			       IWL_BAR_FRAME_RELEASE_STA_MASK);
	tid = le32_get_bits(release->sta_tid,

Annotation

Implementation Notes