File Index
Files and directories
Sign in
FILE

sta.h

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/sta.h C
  1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
  2/*
  3 * Copyright (C) 2024-2025 Intel Corporation
  4 */
  5
  6#ifndef __iwl_mld_sta_h__
  7#define __iwl_mld_sta_h__
  8
  9#include <net/mac80211.h>
 10
 11#include "mld.h"
 12#include "tx.h"
 13
 14/**
 15 * struct iwl_mld_rxq_dup_data - Duplication detection data, per STA & Rx queue
 16 * @last_seq: last sequence per tid.
 17 * @last_sub_frame_idx: the index of the last subframe in an A-MSDU. This value
 18 *	will be zero if the packet is not part of an A-MSDU.
 19 */
 20struct iwl_mld_rxq_dup_data {
 21	__le16 last_seq[IWL_MAX_TID_COUNT + 1];
 22	u8 last_sub_frame_idx[IWL_MAX_TID_COUNT + 1];
 23} ____cacheline_aligned_in_smp;
 24
 25/**
 26 * struct iwl_mld_link_sta - link-level station
 27 *
 28 * This represents the link-level sta - the driver level equivalent to the
 29 * ieee80211_link_sta
 30 *
 31 * @last_rate_n_flags: rate_n_flags from the last &iwl_tlc_update_notif
 32 * @signal_avg: the signal average coming from the firmware
 33 * @in_fw: whether the link STA is uploaded to the FW (false during restart)
 34 * @rcu_head: RCU head for freeing this object
 35 * @fw_id: the FW id of this link sta.
 36 */
 37struct iwl_mld_link_sta {
 38	/* Add here fields that need clean up on restart */
 39	struct_group(zeroed_on_hw_restart,
 40		u32 last_rate_n_flags;
 41		bool in_fw;
 42		s8 signal_avg;
 43	);
 44	/* And here fields that survive a fw restart */
 45	struct rcu_head rcu_head;
 46	u32 fw_id;
 47};
 48
 49#define iwl_mld_link_sta_dereference_check(mld_sta, link_id)		\
 50	rcu_dereference_check((mld_sta)->link[link_id],			\
 51			      lockdep_is_held(&mld_sta->mld->wiphy->mtx))
 52
 53#define for_each_mld_link_sta(mld_sta, link_sta, link_id)		\
 54	for (link_id = 0; link_id < ARRAY_SIZE((mld_sta)->link);	\
 55	     link_id++)							\
 56		if ((link_sta =						\
 57			iwl_mld_link_sta_dereference_check(mld_sta, link_id)))
 58
 59#define IWL_NUM_DEFAULT_KEYS 4
 60
 61/* struct iwl_mld_ptk_pn - Holds Packet Number (PN) per TID.
 62 * @rcu_head: RCU head for freeing this data.
 63 * @pn: Array storing PN for each TID.
 64 */
 65struct iwl_mld_ptk_pn {
 66	struct rcu_head rcu_head;
 67	struct {
 68		u8 pn[IWL_MAX_TID_COUNT][IEEE80211_CCMP_PN_LEN];
 69	} ____cacheline_aligned_in_smp q[];
 70};
 71
 72/**
 73 * struct iwl_mld_per_link_mpdu_counter - per-link TX/RX MPDU counters
 74 *
 75 * @tx: Number of TX MPDUs.
 76 * @rx: Number of RX MPDUs.
 77 */
 78struct iwl_mld_per_link_mpdu_counter {
 79	u32 tx;
 80	u32 rx;
 81};
 82
 83/**
 84 * struct iwl_mld_per_q_mpdu_counter - per-queue MPDU counter
 85 *
 86 * @lock: Needed to protect the counters when modified from statistics.
 87 * @per_link: per-link counters.
 88 * @window_start_time: timestamp of the counting-window start
 89 */
 90struct iwl_mld_per_q_mpdu_counter {
 91	spinlock_t lock;
 92	struct iwl_mld_per_link_mpdu_counter per_link[IWL_FW_MAX_LINK_ID + 1];
 93	unsigned long window_start_time;
 94} ____cacheline_aligned_in_smp;
 95
 96/**
 97 * struct iwl_mld_sta - representation of a station in the driver.
 98 *
 99 * This represent the MLD-level sta, and will not be added to the FW.
100 * Embedded in ieee80211_sta.
101 *
102 * @vif: pointer the vif object.
103 * @sta_state: station state according to enum %ieee80211_sta_state
104 * @sta_type: type of this station. See &enum iwl_fw_sta_type
105 * @mld: a pointer to the iwl_mld object
106 * @dup_data: per queue duplicate packet detection data
107 * @data_tx_ant: stores the last TX antenna index; used for setting
108 *	TX rate_n_flags for injected data frames (toggles on every TX failure).
109 * @tid_to_baid: a simple map of TID to Block-Ack fw id
110 * @deflink: This holds the default link STA information, for non MLO STA all
111 *	link specific STA information is accessed through @deflink or through
112 *	link[0] which points to address of @deflink. For MLO Link STA
113 *	the first added link STA will point to deflink.
114 * @link: reference to Link Sta entries. For Non MLO STA, except 1st link,
115 *	i.e link[0] all links would be assigned to NULL by default and
116 *	would access link information via @deflink or link[0]. For MLO
117 *	STA, first link STA being added will point its link pointer to
118 *	@deflink address and remaining would be allocated and the address
119 *	would be assigned to link[link_id] where link_id is the id assigned
120 *	by the AP.
121 * @ptk_pn: Array of pointers to PTK PN data, used to track the Packet Number
122 *	per key index and per queue (TID).
123 * @mpdu_counters: RX/TX MPDUs counters for each queue.
124 */
125struct iwl_mld_sta {
126	/* Add here fields that need clean up on restart */
127	struct_group(zeroed_on_hw_restart,
128		enum ieee80211_sta_state sta_state;
129		enum iwl_fw_sta_type sta_type;
130	);
131	/* And here fields that survive a fw restart */
132	struct iwl_mld *mld;
133	struct ieee80211_vif *vif;
134	struct iwl_mld_rxq_dup_data *dup_data;
135	u8 tid_to_baid[IWL_MAX_TID_COUNT];
136	u8 data_tx_ant;
137
138	struct iwl_mld_link_sta deflink;
139	struct iwl_mld_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
140	struct iwl_mld_ptk_pn __rcu *ptk_pn[IWL_NUM_DEFAULT_KEYS];
141	struct iwl_mld_per_q_mpdu_counter *mpdu_counters;
142};
143
144static inline struct iwl_mld_sta *
145iwl_mld_sta_from_mac80211(struct ieee80211_sta *sta)
146{
147	return (void *)sta->drv_priv;
148}
149
150static inline void
151iwl_mld_cleanup_sta(void *data, struct ieee80211_sta *sta)
152{
153	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
154	struct iwl_mld_link_sta *mld_link_sta;
155	u8 link_id;
156
157	for (int i = 0; i < ARRAY_SIZE(sta->txq); i++)
158		CLEANUP_STRUCT(iwl_mld_txq_from_mac80211(sta->txq[i]));
159
160	for_each_mld_link_sta(mld_sta, mld_link_sta, link_id) {
161		CLEANUP_STRUCT(mld_link_sta);
162
163		if (!ieee80211_vif_is_mld(mld_sta->vif)) {
164			/* not an MLD STA; only has the deflink with ID zero */
165			WARN_ON(link_id);
166			continue;
167		}
168
169		if (mld_sta->vif->active_links & BIT(link_id))
170			continue;
171
172		/* Should not happen as link removal should always succeed */
173		WARN_ON(1);
174		RCU_INIT_POINTER(mld_sta->link[link_id], NULL);
175		RCU_INIT_POINTER(mld_sta->mld->fw_id_to_link_sta[mld_link_sta->fw_id],
176				 NULL);
177		if (mld_link_sta != &mld_sta->deflink)
178			kfree_rcu(mld_link_sta, rcu_head);
179	}
180
181	CLEANUP_STRUCT(mld_sta);
182}
183
184static inline struct iwl_mld_link_sta *
185iwl_mld_link_sta_from_mac80211(struct ieee80211_link_sta *link_sta)
186{
187	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(link_sta->sta);
188
189	return iwl_mld_link_sta_dereference_check(mld_sta, link_sta->link_id);
190}
191
192int iwl_mld_add_sta(struct iwl_mld *mld, struct ieee80211_sta *sta,
193		    struct ieee80211_vif *vif, enum iwl_fw_sta_type type);
194void iwl_mld_remove_sta(struct iwl_mld *mld, struct ieee80211_sta *sta);
195int iwl_mld_fw_sta_id_from_link_sta(struct iwl_mld *mld,
196				    struct ieee80211_link_sta *link_sta);
197u32 iwl_mld_fw_sta_id_mask(struct iwl_mld *mld, struct ieee80211_sta *sta);
198int iwl_mld_update_all_link_stations(struct iwl_mld *mld,
199				     struct ieee80211_sta *sta);
200void iwl_mld_flush_sta_txqs(struct iwl_mld *mld, struct ieee80211_sta *sta);
201void iwl_mld_wait_sta_txqs_empty(struct iwl_mld *mld,
202				 struct ieee80211_sta *sta);
203void iwl_mld_count_mpdu_rx(struct ieee80211_link_sta *link_sta, int queue,
204			   u32 count);
205void iwl_mld_count_mpdu_tx(struct ieee80211_link_sta *link_sta, u32 count);
206
207/**
208 * struct iwl_mld_int_sta - representation of an internal station
209 * (a station that exist in FW and in driver, but not in mac80211)
210 *
211 * @sta_id: the index of the station in the fw
212 * @queue_id: the if of the queue used by the station
213 * @sta_type: station type. One of &iwl_fw_sta_type
214 */
215struct iwl_mld_int_sta {
216	u8 sta_id;
217	u32 queue_id;
218	enum iwl_fw_sta_type sta_type;
219};
220
221static inline void
222iwl_mld_init_internal_sta(struct iwl_mld_int_sta *internal_sta)
223{
224	internal_sta->sta_id = IWL_INVALID_STA;
225	internal_sta->queue_id = IWL_MLD_INVALID_QUEUE;
226}
227
228static inline void
229iwl_mld_free_internal_sta(struct iwl_mld *mld,
230			  struct iwl_mld_int_sta *internal_sta)
231{
232	if (WARN_ON(internal_sta->sta_id == IWL_INVALID_STA))
233		return;
234
235	RCU_INIT_POINTER(mld->fw_id_to_link_sta[internal_sta->sta_id], NULL);
236	iwl_mld_init_internal_sta(internal_sta);
237}
238
239int iwl_mld_add_bcast_sta(struct iwl_mld *mld,
240			  struct ieee80211_vif *vif,
241			  struct ieee80211_bss_conf *link);
242
243int iwl_mld_add_mcast_sta(struct iwl_mld *mld,
244			  struct ieee80211_vif *vif,
245			  struct ieee80211_bss_conf *link);
246
247int iwl_mld_add_aux_sta(struct iwl_mld *mld,
248			struct iwl_mld_int_sta *internal_sta);
249
250int iwl_mld_add_mon_sta(struct iwl_mld *mld,
251			struct ieee80211_vif *vif,
252			struct ieee80211_bss_conf *link);
253
254void iwl_mld_remove_bcast_sta(struct iwl_mld *mld,
255			      struct ieee80211_vif *vif,
256			      struct ieee80211_bss_conf *link);
257
258void iwl_mld_remove_mcast_sta(struct iwl_mld *mld,
259			      struct ieee80211_vif *vif,
260			      struct ieee80211_bss_conf *link);
261
262void iwl_mld_remove_aux_sta(struct iwl_mld *mld,
263			    struct ieee80211_vif *vif);
264
265void iwl_mld_remove_mon_sta(struct iwl_mld *mld,
266			    struct ieee80211_vif *vif,
267			    struct ieee80211_bss_conf *link);
268
269int iwl_mld_update_link_stas(struct iwl_mld *mld,
270			     struct ieee80211_vif *vif,
271			     struct ieee80211_sta *sta,
272			     u16 old_links, u16 new_links);
273#endif /* __iwl_mld_sta_h__ */
~/ Read-only file preview.