This source file includes following definitions.
- iwl_mvm_bound_iface_iterator
- iwl_mvm_fill_sf_command
- iwl_mvm_sf_config
- iwl_mvm_sf_update
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #include "mvm.h"
63
64
65 struct iwl_mvm_active_iface_iterator_data {
66 struct ieee80211_vif *ignore_vif;
67 u8 sta_vif_ap_sta_id;
68 enum iwl_sf_state sta_vif_state;
69 u32 num_active_macs;
70 };
71
72
73
74
75
76 static void iwl_mvm_bound_iface_iterator(void *_data, u8 *mac,
77 struct ieee80211_vif *vif)
78 {
79 struct iwl_mvm_active_iface_iterator_data *data = _data;
80 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
81
82 if (vif == data->ignore_vif || !mvmvif->phy_ctxt ||
83 vif->type == NL80211_IFTYPE_P2P_DEVICE)
84 return;
85
86 data->num_active_macs++;
87
88 if (vif->type == NL80211_IFTYPE_STATION) {
89 data->sta_vif_ap_sta_id = mvmvif->ap_sta_id;
90 if (vif->bss_conf.assoc)
91 data->sta_vif_state = SF_FULL_ON;
92 else
93 data->sta_vif_state = SF_INIT_OFF;
94 }
95 }
96
97
98
99
100
101 static const
102 __le32 sf_full_timeout_def[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
103 {
104 cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER_DEF),
105 cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER_DEF)
106 },
107 {
108 cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER_DEF),
109 cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER_DEF)
110 },
111 {
112 cpu_to_le32(SF_MCAST_AGING_TIMER_DEF),
113 cpu_to_le32(SF_MCAST_IDLE_TIMER_DEF)
114 },
115 {
116 cpu_to_le32(SF_BA_AGING_TIMER_DEF),
117 cpu_to_le32(SF_BA_IDLE_TIMER_DEF)
118 },
119 {
120 cpu_to_le32(SF_TX_RE_AGING_TIMER_DEF),
121 cpu_to_le32(SF_TX_RE_IDLE_TIMER_DEF)
122 },
123 };
124
125
126
127
128
129 static const __le32 sf_full_timeout[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES] = {
130 {
131 cpu_to_le32(SF_SINGLE_UNICAST_AGING_TIMER),
132 cpu_to_le32(SF_SINGLE_UNICAST_IDLE_TIMER)
133 },
134 {
135 cpu_to_le32(SF_AGG_UNICAST_AGING_TIMER),
136 cpu_to_le32(SF_AGG_UNICAST_IDLE_TIMER)
137 },
138 {
139 cpu_to_le32(SF_MCAST_AGING_TIMER),
140 cpu_to_le32(SF_MCAST_IDLE_TIMER)
141 },
142 {
143 cpu_to_le32(SF_BA_AGING_TIMER),
144 cpu_to_le32(SF_BA_IDLE_TIMER)
145 },
146 {
147 cpu_to_le32(SF_TX_RE_AGING_TIMER),
148 cpu_to_le32(SF_TX_RE_IDLE_TIMER)
149 },
150 };
151
152 static void iwl_mvm_fill_sf_command(struct iwl_mvm *mvm,
153 struct iwl_sf_cfg_cmd *sf_cmd,
154 struct ieee80211_sta *sta)
155 {
156 int i, j, watermark;
157
158 sf_cmd->watermark[SF_LONG_DELAY_ON] = cpu_to_le32(SF_W_MARK_SCAN);
159
160
161
162
163
164 if (sta) {
165 if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
166 switch (sta->rx_nss) {
167 case 1:
168 watermark = SF_W_MARK_SISO;
169 break;
170 case 2:
171 watermark = SF_W_MARK_MIMO2;
172 break;
173 default:
174 watermark = SF_W_MARK_MIMO3;
175 break;
176 }
177 } else {
178 watermark = SF_W_MARK_LEGACY;
179 }
180
181 } else {
182 watermark = SF_W_MARK_MIMO2;
183 }
184 sf_cmd->watermark[SF_FULL_ON] = cpu_to_le32(watermark);
185
186 for (i = 0; i < SF_NUM_SCENARIO; i++) {
187 for (j = 0; j < SF_NUM_TIMEOUT_TYPES; j++) {
188 sf_cmd->long_delay_timeouts[i][j] =
189 cpu_to_le32(SF_LONG_DELAY_AGING_TIMER);
190 }
191 }
192
193 if (sta) {
194 BUILD_BUG_ON(sizeof(sf_full_timeout) !=
195 sizeof(__le32) * SF_NUM_SCENARIO *
196 SF_NUM_TIMEOUT_TYPES);
197
198 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout,
199 sizeof(sf_full_timeout));
200 } else {
201 BUILD_BUG_ON(sizeof(sf_full_timeout_def) !=
202 sizeof(__le32) * SF_NUM_SCENARIO *
203 SF_NUM_TIMEOUT_TYPES);
204
205 memcpy(sf_cmd->full_on_timeouts, sf_full_timeout_def,
206 sizeof(sf_full_timeout_def));
207 }
208
209 }
210
211 static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id,
212 enum iwl_sf_state new_state)
213 {
214 struct iwl_sf_cfg_cmd sf_cmd = {
215 .state = cpu_to_le32(new_state),
216 };
217 struct ieee80211_sta *sta;
218 int ret = 0;
219
220 if (mvm->cfg->disable_dummy_notification)
221 sf_cmd.state |= cpu_to_le32(SF_CFG_DUMMY_NOTIF_OFF);
222
223
224
225
226
227 if (new_state != SF_FULL_ON && mvm->sf_state == new_state)
228 return 0;
229
230 switch (new_state) {
231 case SF_UNINIT:
232 iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
233 break;
234 case SF_FULL_ON:
235 if (sta_id == IWL_MVM_INVALID_STA) {
236 IWL_ERR(mvm,
237 "No station: Cannot switch SF to FULL_ON\n");
238 return -EINVAL;
239 }
240 rcu_read_lock();
241 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
242 if (IS_ERR_OR_NULL(sta)) {
243 IWL_ERR(mvm, "Invalid station id\n");
244 rcu_read_unlock();
245 return -EINVAL;
246 }
247 iwl_mvm_fill_sf_command(mvm, &sf_cmd, sta);
248 rcu_read_unlock();
249 break;
250 case SF_INIT_OFF:
251 iwl_mvm_fill_sf_command(mvm, &sf_cmd, NULL);
252 break;
253 default:
254 WARN_ONCE(1, "Invalid state: %d. not sending Smart Fifo cmd\n",
255 new_state);
256 return -EINVAL;
257 }
258
259 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_SF_CFG_CMD, CMD_ASYNC,
260 sizeof(sf_cmd), &sf_cmd);
261 if (!ret)
262 mvm->sf_state = new_state;
263
264 return ret;
265 }
266
267
268
269
270
271
272 int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
273 bool remove_vif)
274 {
275 enum iwl_sf_state new_state;
276 u8 sta_id = IWL_MVM_INVALID_STA;
277 struct iwl_mvm_vif *mvmvif = NULL;
278 struct iwl_mvm_active_iface_iterator_data data = {
279 .ignore_vif = changed_vif,
280 .sta_vif_state = SF_UNINIT,
281 .sta_vif_ap_sta_id = IWL_MVM_INVALID_STA,
282 };
283
284
285
286
287
288 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) ||
289 (changed_vif && changed_vif->type == NL80211_IFTYPE_P2P_DEVICE))
290 return 0;
291
292 ieee80211_iterate_active_interfaces_atomic(mvm->hw,
293 IEEE80211_IFACE_ITER_NORMAL,
294 iwl_mvm_bound_iface_iterator,
295 &data);
296
297
298 if (changed_vif && !remove_vif)
299 data.num_active_macs++;
300
301 switch (data.num_active_macs) {
302 case 0:
303
304 new_state = SF_INIT_OFF;
305 break;
306 case 1:
307 if (remove_vif) {
308
309
310
311 new_state = data.sta_vif_state;
312 sta_id = data.sta_vif_ap_sta_id;
313 } else {
314 if (WARN_ON(!changed_vif))
315 return -EINVAL;
316 if (changed_vif->type != NL80211_IFTYPE_STATION) {
317 new_state = SF_UNINIT;
318 } else if (changed_vif->bss_conf.assoc &&
319 changed_vif->bss_conf.dtim_period) {
320 mvmvif = iwl_mvm_vif_from_mac80211(changed_vif);
321 sta_id = mvmvif->ap_sta_id;
322 new_state = SF_FULL_ON;
323 } else {
324 new_state = SF_INIT_OFF;
325 }
326 }
327 break;
328 default:
329
330 new_state = SF_UNINIT;
331 }
332 return iwl_mvm_sf_config(mvm, sta_id, new_state);
333 }