• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license.  When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of version 2 of the GNU General Public License as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called COPYING.
26  *
27  * Contact Information:
28  *  Intel Linux Wireless <ilw@linux.intel.com>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
40  *  * Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  *  * Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in
44  *    the documentation and/or other materials provided with the
45  *    distribution.
46  *  * Neither the name Intel Corporation nor the names of its
47  *    contributors may be used to endorse or promote products derived
48  *    from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  *****************************************************************************/
63 
64 #include <linux/etherdevice.h>
65 #include <net/mac80211.h>
66 #include "iwl-io.h"
67 #include "iwl-prph.h"
68 #include "fw-api.h"
69 #include "mvm.h"
70 
71 const u8 iwl_mvm_ac_to_tx_fifo[] = {
72 	IWL_MVM_TX_FIFO_BK,
73 	IWL_MVM_TX_FIFO_BE,
74 	IWL_MVM_TX_FIFO_VI,
75 	IWL_MVM_TX_FIFO_VO,
76 };
77 
78 struct iwl_mvm_mac_iface_iterator_data {
79 	struct iwl_mvm *mvm;
80 	struct ieee80211_vif *vif;
81 	unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
82 	unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
83 	unsigned long used_hw_queues[BITS_TO_LONGS(IWL_MVM_FIRST_AGG_QUEUE)];
84 	enum iwl_tsf_id preferred_tsf;
85 	bool found_vif;
86 };
87 
iwl_mvm_mac_iface_iterator(void * _data,u8 * mac,struct ieee80211_vif * vif)88 static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
89 				       struct ieee80211_vif *vif)
90 {
91 	struct iwl_mvm_mac_iface_iterator_data *data = _data;
92 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
93 	u32 ac;
94 
95 	/* Iterator may already find the interface being added -- skip it */
96 	if (vif == data->vif) {
97 		data->found_vif = true;
98 		return;
99 	}
100 
101 	/* Mark the queues used by the vif */
102 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
103 		if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
104 			__set_bit(vif->hw_queue[ac], data->used_hw_queues);
105 
106 	if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE)
107 		__set_bit(vif->cab_queue, data->used_hw_queues);
108 
109 	/*
110 	 * Mark MAC IDs as used by clearing the available bit, and
111 	 * (below) mark TSFs as used if their existing use is not
112 	 * compatible with the new interface type.
113 	 * No locking or atomic bit operations are needed since the
114 	 * data is on the stack of the caller function.
115 	 */
116 	__clear_bit(mvmvif->id, data->available_mac_ids);
117 
118 	/*
119 	 * The TSF is a hardware/firmware resource, there are 4 and
120 	 * the driver should assign and free them as needed. However,
121 	 * there are cases where 2 MACs should share the same TSF ID
122 	 * for the purpose of clock sync, an optimization to avoid
123 	 * clock drift causing overlapping TBTTs/DTIMs for a GO and
124 	 * client in the system.
125 	 *
126 	 * The firmware will decide according to the MAC type which
127 	 * will be the master and slave. Clients that need to sync
128 	 * with a remote station will be the master, and an AP or GO
129 	 * will be the slave.
130 	 *
131 	 * Depending on the new interface type it can be slaved to
132 	 * or become the master of an existing interface.
133 	 */
134 	switch (data->vif->type) {
135 	case NL80211_IFTYPE_STATION:
136 		/*
137 		 * The new interface is client, so if the existing one
138 		 * we're iterating is an AP, the TSF should be used to
139 		 * avoid drift between the new client and existing AP,
140 		 * the existing AP will get drift updates from the new
141 		 * client context in this case
142 		 */
143 		if (vif->type == NL80211_IFTYPE_AP) {
144 			if (data->preferred_tsf == NUM_TSF_IDS &&
145 			    test_bit(mvmvif->tsf_id, data->available_tsf_ids))
146 				data->preferred_tsf = mvmvif->tsf_id;
147 			return;
148 		}
149 		break;
150 	case NL80211_IFTYPE_AP:
151 		/*
152 		 * The new interface is AP/GO, so should get drift
153 		 * updates from an existing client or use the same
154 		 * TSF as an existing GO. There's no drift between
155 		 * TSFs internally but if they used different TSFs
156 		 * then a new client MAC could update one of them
157 		 * and cause drift that way.
158 		 */
159 		if (vif->type == NL80211_IFTYPE_STATION ||
160 		    vif->type == NL80211_IFTYPE_AP) {
161 			if (data->preferred_tsf == NUM_TSF_IDS &&
162 			    test_bit(mvmvif->tsf_id, data->available_tsf_ids))
163 				data->preferred_tsf = mvmvif->tsf_id;
164 			return;
165 		}
166 		break;
167 	default:
168 		/*
169 		 * For all other interface types there's no need to
170 		 * take drift into account. Either they're exclusive
171 		 * like IBSS and monitor, or we don't care much about
172 		 * their TSF (like P2P Device), but we won't be able
173 		 * to share the TSF resource.
174 		 */
175 		break;
176 	}
177 
178 	/*
179 	 * Unless we exited above, we can't share the TSF resource
180 	 * that the virtual interface we're iterating over is using
181 	 * with the new one, so clear the available bit and if this
182 	 * was the preferred one, reset that as well.
183 	 */
184 	__clear_bit(mvmvif->tsf_id, data->available_tsf_ids);
185 
186 	if (data->preferred_tsf == mvmvif->tsf_id)
187 		data->preferred_tsf = NUM_TSF_IDS;
188 }
189 
190 /*
191  * Get the mask of the queus used by the vif
192  */
iwl_mvm_mac_get_queues_mask(struct iwl_mvm * mvm,struct ieee80211_vif * vif)193 u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
194 				struct ieee80211_vif *vif)
195 {
196 	u32 qmask, ac;
197 
198 	if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
199 		return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
200 
201 	qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
202 		BIT(vif->cab_queue) : 0;
203 
204 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
205 		if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
206 			qmask |= BIT(vif->hw_queue[ac]);
207 
208 	return qmask;
209 }
210 
iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm * mvm,struct ieee80211_vif * vif)211 static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
212 					       struct ieee80211_vif *vif)
213 {
214 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
215 	struct iwl_mvm_mac_iface_iterator_data data = {
216 		.mvm = mvm,
217 		.vif = vif,
218 		.available_mac_ids = { (1 << NUM_MAC_INDEX_DRIVER) - 1 },
219 		.available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
220 		/* no preference yet */
221 		.preferred_tsf = NUM_TSF_IDS,
222 		.used_hw_queues = {
223 			BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
224 			BIT(IWL_MVM_AUX_QUEUE) |
225 			BIT(IWL_MVM_CMD_QUEUE)
226 		},
227 		.found_vif = false,
228 	};
229 	u32 ac;
230 	int ret;
231 
232 	/*
233 	 * Allocate a MAC ID and a TSF for this MAC, along with the queues
234 	 * and other resources.
235 	 */
236 
237 	/*
238 	 * Before the iterator, we start with all MAC IDs and TSFs available.
239 	 *
240 	 * During iteration, all MAC IDs are cleared that are in use by other
241 	 * virtual interfaces, and all TSF IDs are cleared that can't be used
242 	 * by this new virtual interface because they're used by an interface
243 	 * that can't share it with the new one.
244 	 * At the same time, we check if there's a preferred TSF in the case
245 	 * that we should share it with another interface.
246 	 */
247 
248 	/* Currently, MAC ID 0 should be used only for the managed vif */
249 	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
250 		__clear_bit(0, data.available_mac_ids);
251 
252 	ieee80211_iterate_active_interfaces_atomic(
253 		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
254 		iwl_mvm_mac_iface_iterator, &data);
255 
256 	/*
257 	 * In the case we're getting here during resume, it's similar to
258 	 * firmware restart, and with RESUME_ALL the iterator will find
259 	 * the vif being added already.
260 	 * We don't want to reassign any IDs in either case since doing
261 	 * so would probably assign different IDs (as interfaces aren't
262 	 * necessarily added in the same order), but the old IDs were
263 	 * preserved anyway, so skip ID assignment for both resume and
264 	 * recovery.
265 	 */
266 	if (data.found_vif)
267 		return 0;
268 
269 	/* Therefore, in recovery, we can't get here */
270 	WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
271 
272 	mvmvif->id = find_first_bit(data.available_mac_ids,
273 				    NUM_MAC_INDEX_DRIVER);
274 	if (mvmvif->id == NUM_MAC_INDEX_DRIVER) {
275 		IWL_ERR(mvm, "Failed to init MAC context - no free ID!\n");
276 		ret = -EIO;
277 		goto exit_fail;
278 	}
279 
280 	if (data.preferred_tsf != NUM_TSF_IDS)
281 		mvmvif->tsf_id = data.preferred_tsf;
282 	else
283 		mvmvif->tsf_id = find_first_bit(data.available_tsf_ids,
284 						NUM_TSF_IDS);
285 	if (mvmvif->tsf_id == NUM_TSF_IDS) {
286 		IWL_ERR(mvm, "Failed to init MAC context - no free TSF!\n");
287 		ret = -EIO;
288 		goto exit_fail;
289 	}
290 
291 	mvmvif->color = 0;
292 
293 	INIT_LIST_HEAD(&mvmvif->time_event_data.list);
294 	mvmvif->time_event_data.id = TE_MAX;
295 
296 	/* No need to allocate data queues to P2P Device MAC.*/
297 	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
298 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
299 			vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
300 
301 		return 0;
302 	}
303 
304 	/* Find available queues, and allocate them to the ACs */
305 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
306 		u8 queue = find_first_zero_bit(data.used_hw_queues,
307 					       IWL_MVM_FIRST_AGG_QUEUE);
308 
309 		if (queue >= IWL_MVM_FIRST_AGG_QUEUE) {
310 			IWL_ERR(mvm, "Failed to allocate queue\n");
311 			ret = -EIO;
312 			goto exit_fail;
313 		}
314 
315 		__set_bit(queue, data.used_hw_queues);
316 		vif->hw_queue[ac] = queue;
317 	}
318 
319 	/* Allocate the CAB queue for softAP and GO interfaces */
320 	if (vif->type == NL80211_IFTYPE_AP) {
321 		u8 queue = find_first_zero_bit(data.used_hw_queues,
322 					       IWL_MVM_FIRST_AGG_QUEUE);
323 
324 		if (queue >= IWL_MVM_FIRST_AGG_QUEUE) {
325 			IWL_ERR(mvm, "Failed to allocate cab queue\n");
326 			ret = -EIO;
327 			goto exit_fail;
328 		}
329 
330 		vif->cab_queue = queue;
331 	} else {
332 		vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
333 	}
334 
335 	mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT;
336 	mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
337 
338 	return 0;
339 
340 exit_fail:
341 	memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
342 	memset(vif->hw_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(vif->hw_queue));
343 	vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
344 	return ret;
345 }
346 
iwl_mvm_mac_ctxt_init(struct iwl_mvm * mvm,struct ieee80211_vif * vif)347 int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
348 {
349 	u32 ac;
350 	int ret;
351 
352 	lockdep_assert_held(&mvm->mutex);
353 
354 	ret = iwl_mvm_mac_ctxt_allocate_resources(mvm, vif);
355 	if (ret)
356 		return ret;
357 
358 	switch (vif->type) {
359 	case NL80211_IFTYPE_P2P_DEVICE:
360 		iwl_trans_ac_txq_enable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE,
361 					IWL_MVM_TX_FIFO_VO);
362 		break;
363 	case NL80211_IFTYPE_AP:
364 		iwl_trans_ac_txq_enable(mvm->trans, vif->cab_queue,
365 					IWL_MVM_TX_FIFO_VO);
366 		/* fall through */
367 	default:
368 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
369 			iwl_trans_ac_txq_enable(mvm->trans, vif->hw_queue[ac],
370 						iwl_mvm_ac_to_tx_fifo[ac]);
371 		break;
372 	}
373 
374 	return 0;
375 }
376 
iwl_mvm_mac_ctxt_release(struct iwl_mvm * mvm,struct ieee80211_vif * vif)377 void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
378 {
379 	int ac;
380 
381 	lockdep_assert_held(&mvm->mutex);
382 
383 	switch (vif->type) {
384 	case NL80211_IFTYPE_P2P_DEVICE:
385 		iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE);
386 		break;
387 	case NL80211_IFTYPE_AP:
388 		iwl_trans_txq_disable(mvm->trans, vif->cab_queue);
389 		/* fall through */
390 	default:
391 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
392 			iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac]);
393 	}
394 }
395 
iwl_mvm_ack_rates(struct iwl_mvm * mvm,struct ieee80211_vif * vif,enum ieee80211_band band,u8 * cck_rates,u8 * ofdm_rates)396 static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
397 			      struct ieee80211_vif *vif,
398 			      enum ieee80211_band band,
399 			      u8 *cck_rates, u8 *ofdm_rates)
400 {
401 	struct ieee80211_supported_band *sband;
402 	unsigned long basic = vif->bss_conf.basic_rates;
403 	int lowest_present_ofdm = 100;
404 	int lowest_present_cck = 100;
405 	u8 cck = 0;
406 	u8 ofdm = 0;
407 	int i;
408 
409 	sband = mvm->hw->wiphy->bands[band];
410 
411 	for_each_set_bit(i, &basic, BITS_PER_LONG) {
412 		int hw = sband->bitrates[i].hw_value;
413 		if (hw >= IWL_FIRST_OFDM_RATE) {
414 			ofdm |= BIT(hw - IWL_FIRST_OFDM_RATE);
415 			if (lowest_present_ofdm > hw)
416 				lowest_present_ofdm = hw;
417 		} else {
418 			BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
419 
420 			cck |= BIT(hw);
421 			if (lowest_present_cck > hw)
422 				lowest_present_cck = hw;
423 		}
424 	}
425 
426 	/*
427 	 * Now we've got the basic rates as bitmaps in the ofdm and cck
428 	 * variables. This isn't sufficient though, as there might not
429 	 * be all the right rates in the bitmap. E.g. if the only basic
430 	 * rates are 5.5 Mbps and 11 Mbps, we still need to add 1 Mbps
431 	 * and 6 Mbps because the 802.11-2007 standard says in 9.6:
432 	 *
433 	 *    [...] a STA responding to a received frame shall transmit
434 	 *    its Control Response frame [...] at the highest rate in the
435 	 *    BSSBasicRateSet parameter that is less than or equal to the
436 	 *    rate of the immediately previous frame in the frame exchange
437 	 *    sequence ([...]) and that is of the same modulation class
438 	 *    ([...]) as the received frame. If no rate contained in the
439 	 *    BSSBasicRateSet parameter meets these conditions, then the
440 	 *    control frame sent in response to a received frame shall be
441 	 *    transmitted at the highest mandatory rate of the PHY that is
442 	 *    less than or equal to the rate of the received frame, and
443 	 *    that is of the same modulation class as the received frame.
444 	 *
445 	 * As a consequence, we need to add all mandatory rates that are
446 	 * lower than all of the basic rates to these bitmaps.
447 	 */
448 
449 	if (IWL_RATE_24M_INDEX < lowest_present_ofdm)
450 		ofdm |= IWL_RATE_BIT_MSK(24) >> IWL_FIRST_OFDM_RATE;
451 	if (IWL_RATE_12M_INDEX < lowest_present_ofdm)
452 		ofdm |= IWL_RATE_BIT_MSK(12) >> IWL_FIRST_OFDM_RATE;
453 	/* 6M already there or needed so always add */
454 	ofdm |= IWL_RATE_BIT_MSK(6) >> IWL_FIRST_OFDM_RATE;
455 
456 	/*
457 	 * CCK is a bit more complex with DSSS vs. HR/DSSS vs. ERP.
458 	 * Note, however:
459 	 *  - if no CCK rates are basic, it must be ERP since there must
460 	 *    be some basic rates at all, so they're OFDM => ERP PHY
461 	 *    (or we're in 5 GHz, and the cck bitmap will never be used)
462 	 *  - if 11M is a basic rate, it must be ERP as well, so add 5.5M
463 	 *  - if 5.5M is basic, 1M and 2M are mandatory
464 	 *  - if 2M is basic, 1M is mandatory
465 	 *  - if 1M is basic, that's the only valid ACK rate.
466 	 * As a consequence, it's not as complicated as it sounds, just add
467 	 * any lower rates to the ACK rate bitmap.
468 	 */
469 	if (IWL_RATE_11M_INDEX < lowest_present_cck)
470 		cck |= IWL_RATE_BIT_MSK(11) >> IWL_FIRST_CCK_RATE;
471 	if (IWL_RATE_5M_INDEX < lowest_present_cck)
472 		cck |= IWL_RATE_BIT_MSK(5) >> IWL_FIRST_CCK_RATE;
473 	if (IWL_RATE_2M_INDEX < lowest_present_cck)
474 		cck |= IWL_RATE_BIT_MSK(2) >> IWL_FIRST_CCK_RATE;
475 	/* 1M already there or needed so always add */
476 	cck |= IWL_RATE_BIT_MSK(1) >> IWL_FIRST_CCK_RATE;
477 
478 	*cck_rates = cck;
479 	*ofdm_rates = ofdm;
480 }
481 
iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm * mvm,struct ieee80211_vif * vif,struct iwl_mac_ctx_cmd * cmd,u32 action)482 static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
483 					struct ieee80211_vif *vif,
484 					struct iwl_mac_ctx_cmd *cmd,
485 					u32 action)
486 {
487 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
488 	struct ieee80211_chanctx_conf *chanctx;
489 	u8 cck_ack_rates, ofdm_ack_rates;
490 	int i;
491 
492 	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
493 							    mvmvif->color));
494 	cmd->action = cpu_to_le32(action);
495 
496 	switch (vif->type) {
497 	case NL80211_IFTYPE_STATION:
498 		if (vif->p2p)
499 			cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_STA);
500 		else
501 			cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_BSS_STA);
502 		break;
503 	case NL80211_IFTYPE_AP:
504 		cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_GO);
505 		break;
506 	case NL80211_IFTYPE_MONITOR:
507 		cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_LISTENER);
508 		break;
509 	case NL80211_IFTYPE_P2P_DEVICE:
510 		cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_P2P_DEVICE);
511 		break;
512 	case NL80211_IFTYPE_ADHOC:
513 		cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_IBSS);
514 		break;
515 	default:
516 		WARN_ON_ONCE(1);
517 	}
518 
519 	cmd->tsf_id = cpu_to_le32(mvmvif->tsf_id);
520 
521 	memcpy(cmd->node_addr, vif->addr, ETH_ALEN);
522 	if (vif->bss_conf.bssid)
523 		memcpy(cmd->bssid_addr, vif->bss_conf.bssid, ETH_ALEN);
524 	else
525 		eth_broadcast_addr(cmd->bssid_addr);
526 
527 	rcu_read_lock();
528 	chanctx = rcu_dereference(vif->chanctx_conf);
529 	iwl_mvm_ack_rates(mvm, vif, chanctx ? chanctx->def.chan->band
530 					    : IEEE80211_BAND_2GHZ,
531 			  &cck_ack_rates, &ofdm_ack_rates);
532 	rcu_read_unlock();
533 
534 	cmd->cck_rates = cpu_to_le32((u32)cck_ack_rates);
535 	cmd->ofdm_rates = cpu_to_le32((u32)ofdm_ack_rates);
536 
537 	cmd->cck_short_preamble =
538 		cpu_to_le32(vif->bss_conf.use_short_preamble ?
539 			    MAC_FLG_SHORT_PREAMBLE : 0);
540 	cmd->short_slot =
541 		cpu_to_le32(vif->bss_conf.use_short_slot ?
542 			    MAC_FLG_SHORT_SLOT : 0);
543 
544 	for (i = 0; i < AC_NUM; i++) {
545 		cmd->ac[i].cw_min = cpu_to_le16(mvmvif->queue_params[i].cw_min);
546 		cmd->ac[i].cw_max = cpu_to_le16(mvmvif->queue_params[i].cw_max);
547 		cmd->ac[i].aifsn = mvmvif->queue_params[i].aifs;
548 		cmd->ac[i].edca_txop =
549 			cpu_to_le16(mvmvif->queue_params[i].txop * 32);
550 		cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]);
551 	}
552 
553 	if (vif->bss_conf.qos)
554 		cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
555 
556 	/* Don't use cts to self as the fw doesn't support it currently. */
557 	if (vif->bss_conf.use_cts_prot)
558 		cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
559 
560 	/*
561 	 * I think that we should enable these 2 flags regardless the HT PROT
562 	 * fields in the HT IE, but I am not sure. Someone knows whom to ask?...
563 	 */
564 	if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
565 		cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
566 		cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_HT_PROT |
567 						     MAC_PROT_FLG_FAT_PROT);
568 	}
569 
570 	cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
571 }
572 
iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm * mvm,struct iwl_mac_ctx_cmd * cmd)573 static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
574 				     struct iwl_mac_ctx_cmd *cmd)
575 {
576 	int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,
577 				       sizeof(*cmd), cmd);
578 	if (ret)
579 		IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",
580 			le32_to_cpu(cmd->action), ret);
581 	return ret;
582 }
583 
584 /*
585  * Fill the specific data for mac context of type station or p2p client
586  */
iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm * mvm,struct ieee80211_vif * vif,struct iwl_mac_data_sta * ctxt_sta,bool force_assoc_off)587 static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
588 					  struct ieee80211_vif *vif,
589 					  struct iwl_mac_data_sta *ctxt_sta,
590 					  bool force_assoc_off)
591 {
592 	/* We need the dtim_period to set the MAC as associated */
593 	if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
594 	    !force_assoc_off) {
595 		u32 dtim_offs;
596 
597 		/*
598 		 * The DTIM count counts down, so when it is N that means N
599 		 * more beacon intervals happen until the DTIM TBTT. Therefore
600 		 * add this to the current time. If that ends up being in the
601 		 * future, the firmware will handle it.
602 		 *
603 		 * Also note that the system_timestamp (which we get here as
604 		 * "sync_device_ts") and TSF timestamp aren't at exactly the
605 		 * same offset in the frame -- the TSF is at the first symbol
606 		 * of the TSF, the system timestamp is at signal acquisition
607 		 * time. This means there's an offset between them of at most
608 		 * a few hundred microseconds (24 * 8 bits + PLCP time gives
609 		 * 384us in the longest case), this is currently not relevant
610 		 * as the firmware wakes up around 2ms before the TBTT.
611 		 */
612 		dtim_offs = vif->bss_conf.sync_dtim_count *
613 				vif->bss_conf.beacon_int;
614 		/* convert TU to usecs */
615 		dtim_offs *= 1024;
616 
617 		ctxt_sta->dtim_tsf =
618 			cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs);
619 		ctxt_sta->dtim_time =
620 			cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs);
621 
622 		IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n",
623 			       le64_to_cpu(ctxt_sta->dtim_tsf),
624 			       le32_to_cpu(ctxt_sta->dtim_time),
625 			       dtim_offs);
626 
627 		ctxt_sta->is_assoc = cpu_to_le32(1);
628 	} else {
629 		ctxt_sta->is_assoc = cpu_to_le32(0);
630 	}
631 
632 	ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int);
633 	ctxt_sta->bi_reciprocal =
634 		cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
635 	ctxt_sta->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
636 					      vif->bss_conf.dtim_period);
637 	ctxt_sta->dtim_reciprocal =
638 		cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int *
639 					       vif->bss_conf.dtim_period));
640 
641 	ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
642 	ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);
643 }
644 
iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)645 static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
646 					struct ieee80211_vif *vif,
647 					u32 action)
648 {
649 	struct iwl_mac_ctx_cmd cmd = {};
650 
651 	WARN_ON(vif->type != NL80211_IFTYPE_STATION || vif->p2p);
652 
653 	/* Fill the common data for all mac context types */
654 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
655 
656 	/* Allow beacons to pass through as long as we are not associated,or we
657 	 * do not have dtim period information */
658 	if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period)
659 		cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
660 	else
661 		cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);
662 
663 	/* Fill the data specific for station mode */
664 	iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta,
665 				      action == FW_CTXT_ACTION_ADD);
666 
667 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
668 }
669 
iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)670 static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
671 					   struct ieee80211_vif *vif,
672 					   u32 action)
673 {
674 	struct iwl_mac_ctx_cmd cmd = {};
675 	struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
676 
677 	WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);
678 
679 	/* Fill the common data for all mac context types */
680 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
681 
682 	/* Fill the data specific for station mode */
683 	iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta,
684 				      action == FW_CTXT_ACTION_ADD);
685 
686 	cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
687 					IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
688 
689 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
690 }
691 
iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)692 static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
693 					 struct ieee80211_vif *vif,
694 					 u32 action)
695 {
696 	struct iwl_mac_ctx_cmd cmd = {};
697 
698 	WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
699 
700 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
701 
702 	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
703 				       MAC_FILTER_IN_CONTROL_AND_MGMT |
704 				       MAC_FILTER_IN_BEACON |
705 				       MAC_FILTER_IN_PROBE_REQUEST);
706 
707 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
708 }
709 
710 struct iwl_mvm_go_iterator_data {
711 	bool go_active;
712 };
713 
iwl_mvm_go_iterator(void * _data,u8 * mac,struct ieee80211_vif * vif)714 static void iwl_mvm_go_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif)
715 {
716 	struct iwl_mvm_go_iterator_data *data = _data;
717 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
718 
719 	if (vif->type == NL80211_IFTYPE_AP && vif->p2p && mvmvif->ap_active)
720 		data->go_active = true;
721 }
722 
iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)723 static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
724 					   struct ieee80211_vif *vif,
725 					   u32 action)
726 {
727 	struct iwl_mac_ctx_cmd cmd = {};
728 	struct iwl_mvm_go_iterator_data data = {};
729 
730 	WARN_ON(vif->type != NL80211_IFTYPE_P2P_DEVICE);
731 
732 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
733 
734 	cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
735 
736 	/* Override the filter flags to accept only probe requests */
737 	cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
738 
739 	/*
740 	 * This flag should be set to true when the P2P Device is
741 	 * discoverable and there is at least another active P2P GO. Settings
742 	 * this flag will allow the P2P Device to be discoverable on other
743 	 * channels in addition to its listen channel.
744 	 * Note that this flag should not be set in other cases as it opens the
745 	 * Rx filters on all MAC and increases the number of interrupts.
746 	 */
747 	ieee80211_iterate_active_interfaces_atomic(
748 		mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
749 		iwl_mvm_go_iterator, &data);
750 
751 	cmd.p2p_dev.is_disc_extended = cpu_to_le32(data.go_active ? 1 : 0);
752 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
753 }
754 
iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm * mvm,struct iwl_mac_beacon_cmd * beacon_cmd,u8 * beacon,u32 frame_size)755 static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
756 				     struct iwl_mac_beacon_cmd *beacon_cmd,
757 				     u8 *beacon, u32 frame_size)
758 {
759 	u32 tim_idx;
760 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
761 
762 	/* The index is relative to frame start but we start looking at the
763 	 * variable-length part of the beacon. */
764 	tim_idx = mgmt->u.beacon.variable - beacon;
765 
766 	/* Parse variable-length elements of beacon to find WLAN_EID_TIM */
767 	while ((tim_idx < (frame_size - 2)) &&
768 			(beacon[tim_idx] != WLAN_EID_TIM))
769 		tim_idx += beacon[tim_idx+1] + 2;
770 
771 	/* If TIM field was found, set variables */
772 	if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
773 		beacon_cmd->tim_idx = cpu_to_le32(tim_idx);
774 		beacon_cmd->tim_size = cpu_to_le32((u32)beacon[tim_idx+1]);
775 	} else {
776 		IWL_WARN(mvm, "Unable to find TIM Element in beacon\n");
777 	}
778 }
779 
iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm * mvm,struct ieee80211_vif * vif,struct sk_buff * beacon)780 static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
781 					struct ieee80211_vif *vif,
782 					struct sk_buff *beacon)
783 {
784 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
785 	struct iwl_host_cmd cmd = {
786 		.id = BEACON_TEMPLATE_CMD,
787 		.flags = CMD_ASYNC,
788 	};
789 	struct iwl_mac_beacon_cmd beacon_cmd = {};
790 	struct ieee80211_tx_info *info;
791 	u32 beacon_skb_len;
792 	u32 rate;
793 
794 	if (WARN_ON(!beacon))
795 		return -EINVAL;
796 
797 	beacon_skb_len = beacon->len;
798 
799 	/* TODO: for now the beacon template id is set to be the mac context id.
800 	 * Might be better to handle it as another resource ... */
801 	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
802 
803 	/* Set up TX command fields */
804 	beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len);
805 	beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id;
806 	beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
807 	beacon_cmd.tx.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
808 					     TX_CMD_FLG_BT_DIS  |
809 					     TX_CMD_FLG_TSF);
810 
811 	mvm->mgmt_last_antenna_idx =
812 		iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
813 				     mvm->mgmt_last_antenna_idx);
814 
815 	beacon_cmd.tx.rate_n_flags =
816 		cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
817 			    RATE_MCS_ANT_POS);
818 
819 	info = IEEE80211_SKB_CB(beacon);
820 
821 	if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) {
822 		rate = IWL_FIRST_OFDM_RATE;
823 	} else {
824 		rate = IWL_FIRST_CCK_RATE;
825 		beacon_cmd.tx.rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK);
826 	}
827 	beacon_cmd.tx.rate_n_flags |=
828 		cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate));
829 
830 	/* Set up TX beacon command fields */
831 	iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd,
832 				 beacon->data,
833 				 beacon_skb_len);
834 
835 	/* Submit command */
836 	cmd.len[0] = sizeof(beacon_cmd);
837 	cmd.data[0] = &beacon_cmd;
838 	cmd.dataflags[0] = 0;
839 	cmd.len[1] = beacon_skb_len;
840 	cmd.data[1] = beacon->data;
841 	cmd.dataflags[1] = IWL_HCMD_DFL_DUP;
842 
843 	return iwl_mvm_send_cmd(mvm, &cmd);
844 }
845 
846 /* The beacon template for the AP/GO context has changed and needs update */
iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm * mvm,struct ieee80211_vif * vif)847 int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
848 				    struct ieee80211_vif *vif)
849 {
850 	struct sk_buff *beacon;
851 	int ret;
852 
853 	WARN_ON(vif->type != NL80211_IFTYPE_AP);
854 
855 	beacon = ieee80211_beacon_get(mvm->hw, vif);
856 	if (!beacon)
857 		return -ENOMEM;
858 
859 	ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
860 	dev_kfree_skb(beacon);
861 	return ret;
862 }
863 
864 /*
865  * Fill the specific data for mac context of type AP of P2P GO
866  */
iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm * mvm,struct ieee80211_vif * vif,struct iwl_mac_data_ap * ctxt_ap,bool add)867 static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
868 					 struct ieee80211_vif *vif,
869 					 struct iwl_mac_data_ap *ctxt_ap,
870 					 bool add)
871 {
872 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
873 
874 	ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
875 	ctxt_ap->bi_reciprocal =
876 		cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
877 	ctxt_ap->dtim_interval = cpu_to_le32(vif->bss_conf.beacon_int *
878 					     vif->bss_conf.dtim_period);
879 	ctxt_ap->dtim_reciprocal =
880 		cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int *
881 					       vif->bss_conf.dtim_period));
882 
883 	ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
884 
885 	/*
886 	 * Only read the system time when the MAC is being added, when we
887 	 * just modify the MAC then we should keep the time -- the firmware
888 	 * can otherwise have a "jumping" TBTT.
889 	 */
890 	if (add)
891 		mvmvif->ap_beacon_time =
892 			iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
893 
894 	ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
895 
896 	ctxt_ap->beacon_tsf = 0; /* unused */
897 
898 	/* TODO: Assume that the beacon id == mac context id */
899 	ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
900 }
901 
iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)902 static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
903 				   struct ieee80211_vif *vif,
904 				   u32 action)
905 {
906 	struct iwl_mac_ctx_cmd cmd = {};
907 
908 	WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p);
909 
910 	/* Fill the common data for all mac context types */
911 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
912 
913 	/* Also enable probe requests to pass */
914 	cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
915 
916 	/* Fill the data specific for ap mode */
917 	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
918 				     action == FW_CTXT_ACTION_ADD);
919 
920 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
921 }
922 
iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)923 static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
924 				   struct ieee80211_vif *vif,
925 				   u32 action)
926 {
927 	struct iwl_mac_ctx_cmd cmd = {};
928 	struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
929 
930 	WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
931 
932 	/* Fill the common data for all mac context types */
933 	iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
934 
935 	/* Fill the data specific for GO mode */
936 	iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
937 				     action == FW_CTXT_ACTION_ADD);
938 
939 	cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
940 					IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
941 	cmd.go.opp_ps_enabled =
942 			cpu_to_le32(!!(noa->oppps_ctwindow &
943 					IEEE80211_P2P_OPPPS_ENABLE_BIT));
944 
945 	return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
946 }
947 
iwl_mvm_mac_ctx_send(struct iwl_mvm * mvm,struct ieee80211_vif * vif,u32 action)948 static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
949 				u32 action)
950 {
951 	switch (vif->type) {
952 	case NL80211_IFTYPE_STATION:
953 		if (!vif->p2p)
954 			return iwl_mvm_mac_ctxt_cmd_station(mvm, vif,
955 							    action);
956 		else
957 			return iwl_mvm_mac_ctxt_cmd_p2p_client(mvm, vif,
958 							       action);
959 		break;
960 	case NL80211_IFTYPE_AP:
961 		if (!vif->p2p)
962 			return iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, action);
963 		else
964 			return iwl_mvm_mac_ctxt_cmd_go(mvm, vif, action);
965 		break;
966 	case NL80211_IFTYPE_MONITOR:
967 		return iwl_mvm_mac_ctxt_cmd_listener(mvm, vif, action);
968 	case NL80211_IFTYPE_P2P_DEVICE:
969 		return iwl_mvm_mac_ctxt_cmd_p2p_device(mvm, vif, action);
970 	default:
971 		break;
972 	}
973 
974 	return -EOPNOTSUPP;
975 }
976 
iwl_mvm_mac_ctxt_add(struct iwl_mvm * mvm,struct ieee80211_vif * vif)977 int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
978 {
979 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
980 	int ret;
981 
982 	if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
983 		      vif->addr, ieee80211_vif_type_p2p(vif)))
984 		return -EIO;
985 
986 	ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD);
987 	if (ret)
988 		return ret;
989 
990 	mvmvif->uploaded = true;
991 	return 0;
992 }
993 
iwl_mvm_mac_ctxt_changed(struct iwl_mvm * mvm,struct ieee80211_vif * vif)994 int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
995 {
996 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
997 
998 	if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
999 		      vif->addr, ieee80211_vif_type_p2p(vif)))
1000 		return -EIO;
1001 
1002 	return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY);
1003 }
1004 
iwl_mvm_mac_ctxt_remove(struct iwl_mvm * mvm,struct ieee80211_vif * vif)1005 int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1006 {
1007 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1008 	struct iwl_mac_ctx_cmd cmd;
1009 	int ret;
1010 
1011 	if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
1012 		      vif->addr, ieee80211_vif_type_p2p(vif)))
1013 		return -EIO;
1014 
1015 	memset(&cmd, 0, sizeof(cmd));
1016 
1017 	cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
1018 							   mvmvif->color));
1019 	cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
1020 
1021 	ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,
1022 				   sizeof(cmd), &cmd);
1023 	if (ret) {
1024 		IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);
1025 		return ret;
1026 	}
1027 
1028 	mvmvif->uploaded = false;
1029 	return 0;
1030 }
1031 
iwl_mvm_rx_beacon_notif(struct iwl_mvm * mvm,struct iwl_rx_cmd_buffer * rxb,struct iwl_device_cmd * cmd)1032 int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1033 			    struct iwl_rx_cmd_buffer *rxb,
1034 			    struct iwl_device_cmd *cmd)
1035 {
1036 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
1037 	struct iwl_beacon_notif *beacon = (void *)pkt->data;
1038 	u16 status __maybe_unused =
1039 		le16_to_cpu(beacon->beacon_notify_hdr.status.status);
1040 	u32 rate __maybe_unused =
1041 		le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
1042 
1043 	IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
1044 		     status & TX_STATUS_MSK,
1045 		     beacon->beacon_notify_hdr.failure_frame,
1046 		     le64_to_cpu(beacon->tsf),
1047 		     rate);
1048 	return 0;
1049 }
1050