Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/iwlwifi/mld/mlo.h
48285 views
1
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
2
/*
3
* Copyright (C) 2024-2025 Intel Corporation
4
*/
5
#ifndef __iwl_mld_mlo_h__
6
#define __iwl_mld_mlo_h__
7
8
#include <linux/ieee80211.h>
9
#include <linux/types.h>
10
#include <net/mac80211.h>
11
#include "iwl-config.h"
12
#include "iwl-trans.h"
13
#include "iface.h"
14
#include "phy.h"
15
16
struct iwl_mld;
17
18
void iwl_mld_emlsr_prevent_done_wk(struct wiphy *wiphy, struct wiphy_work *wk);
19
void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy,
20
struct wiphy_work *wk);
21
22
static inline bool iwl_mld_emlsr_active(struct ieee80211_vif *vif)
23
{
24
/* Set on phy context activation, so should be a good proxy */
25
return !!(vif->driver_flags & IEEE80211_VIF_EML_ACTIVE);
26
}
27
28
static inline bool iwl_mld_vif_has_emlsr_cap(struct ieee80211_vif *vif)
29
{
30
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
31
32
/* We only track/permit EMLSR state once authorized */
33
if (!mld_vif->authorized)
34
return false;
35
36
/* No EMLSR on dual radio devices */
37
return ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION &&
38
ieee80211_vif_is_mld(vif) &&
39
vif->cfg.eml_cap & IEEE80211_EML_CAP_EMLSR_SUPP &&
40
!CSR_HW_RFID_IS_CDB(mld_vif->mld->trans->info.hw_rf_id);
41
}
42
43
static inline int
44
iwl_mld_max_active_links(struct iwl_mld *mld, struct ieee80211_vif *vif)
45
{
46
if (vif->type == NL80211_IFTYPE_AP)
47
return mld->fw->ucode_capa.num_beacons;
48
49
if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)
50
return IWL_FW_MAX_ACTIVE_LINKS_NUM;
51
52
/* For now, do not accept more links on other interface types */
53
return 1;
54
}
55
56
static inline int
57
iwl_mld_count_active_links(struct iwl_mld *mld, struct ieee80211_vif *vif)
58
{
59
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
60
struct iwl_mld_link *mld_link;
61
int n_active = 0;
62
63
for_each_mld_vif_valid_link(mld_vif, mld_link) {
64
if (rcu_access_pointer(mld_link->chan_ctx))
65
n_active++;
66
}
67
68
return n_active;
69
}
70
71
static inline u8 iwl_mld_get_primary_link(struct ieee80211_vif *vif)
72
{
73
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
74
75
lockdep_assert_wiphy(mld_vif->mld->wiphy);
76
77
if (!ieee80211_vif_is_mld(vif) || WARN_ON(!vif->active_links))
78
return 0;
79
80
/* In AP mode, there is no primary link */
81
if (vif->type == NL80211_IFTYPE_AP)
82
return __ffs(vif->active_links);
83
84
if (iwl_mld_emlsr_active(vif) &&
85
!WARN_ON(!(BIT(mld_vif->emlsr.primary) & vif->active_links)))
86
return mld_vif->emlsr.primary;
87
88
return __ffs(vif->active_links);
89
}
90
91
/*
92
* For non-MLO/single link, this will return the deflink/single active link,
93
* respectively
94
*/
95
static inline u8 iwl_mld_get_other_link(struct ieee80211_vif *vif, u8 link_id)
96
{
97
switch (hweight16(vif->active_links)) {
98
case 0:
99
return 0;
100
default:
101
WARN_ON(1);
102
fallthrough;
103
case 1:
104
return __ffs(vif->active_links);
105
case 2:
106
return __ffs(vif->active_links & ~BIT(link_id));
107
}
108
}
109
110
s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld,
111
const struct cfg80211_chan_def *chandef,
112
bool low);
113
114
/* EMLSR block/unblock and exit */
115
void iwl_mld_block_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
116
enum iwl_mld_emlsr_blocked reason, u8 link_to_keep);
117
int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif,
118
enum iwl_mld_emlsr_blocked reason, u8 link_to_keep);
119
void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
120
enum iwl_mld_emlsr_blocked reason);
121
void iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
122
enum iwl_mld_emlsr_exit exit, u8 link_to_keep);
123
124
int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,
125
int pending_link_changes);
126
127
void iwl_mld_handle_emlsr_mode_notif(struct iwl_mld *mld,
128
struct iwl_rx_packet *pkt);
129
void iwl_mld_handle_emlsr_trans_fail_notif(struct iwl_mld *mld,
130
struct iwl_rx_packet *pkt);
131
132
void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk);
133
void iwl_mld_emlsr_unblock_tpt_wk(struct wiphy *wiphy, struct wiphy_work *wk);
134
135
void iwl_mld_select_links(struct iwl_mld *mld);
136
137
void iwl_mld_emlsr_check_bt(struct iwl_mld *mld);
138
139
void iwl_mld_emlsr_check_chan_load(struct ieee80211_hw *hw,
140
struct iwl_mld_phy *phy,
141
u32 prev_chan_load_not_by_us);
142
143
/**
144
* iwl_mld_retry_emlsr - Retry entering EMLSR
145
* @mld: MLD context
146
* @vif: VIF to retry EMLSR on
147
*
148
* Retry entering EMLSR on the given VIF.
149
* Use this if one of the parameters that can prevent EMLSR has changed.
150
*/
151
void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif);
152
153
struct iwl_mld_link_sel_data {
154
u8 link_id;
155
const struct cfg80211_chan_def *chandef;
156
s32 signal;
157
u16 grade;
158
};
159
160
void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld);
161
162
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
163
u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif,
164
struct iwl_mld_link_sel_data *a,
165
struct iwl_mld_link_sel_data *b);
166
#endif
167
168
void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld);
169
void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld);
170
171
#endif /* __iwl_mld_mlo_h__ */
172
173