• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * STA and AP APIs for XRadio drivers
3  *
4  * Copyright (c) 2013
5  * Xradio Technology Co., Ltd. <www.xradiotech.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 
12 #include "xradio.h"
13 #include "sta.h"
14 #include "ap.h"
15 #include "bh.h"
16 #include "net/mac80211.h"
17 
18 #define XRADIO_LINK_ID_GC_TIMEOUT        ((unsigned long)(10 * HZ))
19 #define XRADIO_ENABLE_ARP_FILTER_OFFLOAD  3
20 
21 #ifndef ERP_INFO_BYTE_OFFSET
22 #define ERP_INFO_BYTE_OFFSET 2
23 #endif
24 
25 #ifdef IPV6_FILTERING
26 #define XRADIO_ENABLE_NDP_FILTER_OFFLOAD	3
27 #endif /*IPV6_FILTERING */
28 
29 static int xradio_upload_beacon(struct xradio_vif *priv);
30 #ifdef PROBE_RESP_EXTRA_IE
31 static int xradio_upload_proberesp(struct xradio_vif *priv);
32 #endif
33 static int xradio_upload_pspoll(struct xradio_vif *priv);
34 static int xradio_upload_null(struct xradio_vif *priv);
35 static int xradio_upload_qosnull(struct xradio_vif *priv);
36 static int xradio_start_ap(struct xradio_vif *priv);
37 static int xradio_update_beaconing(struct xradio_vif *priv);
38 /*
39 static int xradio_enable_beaconing(struct xradio_vif *priv,
40 				   bool enable);
41 */
42 static void __xradio_sta_notify(struct xradio_vif *priv,
43 				enum sta_notify_cmd notify_cmd, int link_id);
44 
45 /* ******************************************************************** */
46 /* AP API */
xradio_sta_add(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)47 int xradio_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
48 		   struct ieee80211_sta *sta)
49 {
50 	struct xradio_sta_priv *sta_priv =
51 	    (struct xradio_sta_priv *)&sta->drv_priv;
52 	struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
53 	struct xradio_link_entry *entry;
54 	struct sk_buff *skb;
55 #ifdef AP_AGGREGATE_FW_FIX
56 	struct xradio_common *hw_priv = hw->priv;
57 #endif
58 
59 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
60 	if (!atomic_read(&priv->enabled)) {
61 		ap_printk(XRADIO_DBG_NIY, "%s vif(type=%d) is not enable!\n",
62 				__func__, vif->type);
63 		return 0;
64 	}
65 
66 #ifdef P2P_MULTIVIF
67 	SYS_WARN(priv->if_id == XRWL_GENERIC_IF_ID);
68 #endif
69 
70 	if (priv->mode != NL80211_IFTYPE_AP) {
71 		return 0;
72 	}
73 
74 	sta_priv->priv = priv;
75 	sta_priv->link_id = xradio_find_link_id(priv, sta->addr);
76 	if (SYS_WARN(!sta_priv->link_id)) {
77 		/* Impossible error */
78 		ap_printk(XRADIO_DBG_ERROR, "No more link IDs available.\n");
79 		return -ENOENT;
80 	}
81 
82 	entry = &priv->link_id_db[sta_priv->link_id - 1];
83 	spin_lock_bh(&priv->ps_state_lock);
84 	if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) ==
85 	    IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) {
86 		priv->sta_asleep_mask |= BIT(sta_priv->link_id);
87 	}
88 	entry->status = XRADIO_LINK_HARD;
89 	while ((skb = skb_dequeue(&entry->rx_queue)))
90 		mac80211_rx_irqsafe(priv->hw, skb);
91 	spin_unlock_bh(&priv->ps_state_lock);
92 
93 #ifdef AP_AGGREGATE_FW_FIX
94 	hw_priv->connected_sta_cnt++;
95 	if (hw_priv->connected_sta_cnt > 1 &&
96 		WSM_VERSION_BF(hw_priv->wsm_caps, 8, 39)) {
97 		wsm_lock_tx(hw_priv);
98 		SYS_WARN(wsm_set_block_ack_policy(hw_priv,
99 						  XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
100 						  XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
101 						  priv->if_id));
102 		wsm_unlock_tx(hw_priv);
103 		ap_printk(XRADIO_DBG_WARN, "%s: disable BA.\n", __func__);
104 	}
105 #endif
106 
107 	return 0;
108 }
109 
xradio_sta_remove(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)110 int xradio_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
111 		      struct ieee80211_sta *sta)
112 {
113 	struct xradio_common *hw_priv = hw->priv;
114 	struct xradio_sta_priv *sta_priv =
115 	    (struct xradio_sta_priv *)&sta->drv_priv;
116 	struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
117 	struct xradio_link_entry *entry;
118 	int suspend_lock_state;
119 
120 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
121 	suspend_lock_state = atomic_cmpxchg(&hw_priv->suspend_lock_state,
122 								XRADIO_SUSPEND_LOCK_IDEL, XRADIO_SUSPEND_LOCK_OTHERS);
123 	if (suspend_lock_state == XRADIO_SUSPEND_LOCK_SUSPEND) {
124 		sta_printk(XRADIO_DBG_WARN,
125 				"%s:refuse because of suspend\n", __func__);
126 		return -EBUSY;
127 	}
128 	down(&hw_priv->conf_lock);
129 	atomic_set(&hw_priv->suspend_lock_state, XRADIO_SUSPEND_LOCK_IDEL);
130 
131 	if (!atomic_read(&priv->enabled)) {
132 		up(&hw_priv->conf_lock);
133 		ap_printk(XRADIO_DBG_NIY, "%s vif(type=%d) is not enable!\n",
134 				__func__, vif->type);
135 		return 0;
136 	}
137 
138 #ifdef P2P_MULTIVIF
139 	SYS_WARN(priv->if_id == XRWL_GENERIC_IF_ID);
140 #endif
141 
142 	if (priv->mode != NL80211_IFTYPE_AP || !sta_priv->link_id) {
143 		up(&hw_priv->conf_lock);
144 		ap_printk(XRADIO_DBG_NIY, "no station to remove\n");
145 		return 0;
146 	}
147 
148 	entry = &priv->link_id_db[sta_priv->link_id - 1];
149 	spin_lock_bh(&priv->ps_state_lock);
150 	entry->status = XRADIO_LINK_RESERVE;
151 	entry->timestamp = jiffies;
152 	wsm_lock_tx_async(hw_priv);
153 	if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
154 		wsm_unlock_tx(hw_priv);
155 	spin_unlock_bh(&priv->ps_state_lock);
156 	up(&hw_priv->conf_lock);
157 	flush_workqueue(hw_priv->workqueue);
158 	flush_workqueue(hw_priv->spare_workqueue);
159 
160 #ifdef AP_AGGREGATE_FW_FIX
161 	hw_priv->connected_sta_cnt--;
162 	if (hw_priv->connected_sta_cnt <= 1 &&
163 		WSM_VERSION_BF(hw_priv->wsm_caps, 8, 39)) {
164 		if ((priv->if_id != 1) ||
165 		    ((priv->if_id == 1) && hw_priv->is_go_thru_go_neg)) {
166 			wsm_lock_tx(hw_priv);
167 			SYS_WARN(wsm_set_block_ack_policy(hw_priv,
168 							  XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
169 							  XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
170 							  priv->if_id));
171 			wsm_unlock_tx(hw_priv);
172 		}
173 	}
174 #endif
175 
176 	return 0;
177 }
178 
__xradio_sta_notify(struct xradio_vif * priv,enum sta_notify_cmd notify_cmd,int link_id)179 static void __xradio_sta_notify(struct xradio_vif *priv,
180 				enum sta_notify_cmd notify_cmd, int link_id)
181 {
182 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
183 	u32 bit, prev;
184 
185 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
186 
187 	/* Zero link id means "for all link IDs" */
188 	if (link_id)
189 		bit = BIT(link_id);
190 	else if (WARN_ON_ONCE(notify_cmd != STA_NOTIFY_AWAKE))
191 		bit = 0;
192 	else
193 		bit = priv->link_id_map;
194 	prev = priv->sta_asleep_mask & bit;
195 
196 	switch (notify_cmd) {
197 	case STA_NOTIFY_SLEEP:
198 		if (!prev) {
199 			if (priv->buffered_multicasts && !priv->sta_asleep_mask)
200 				queue_work(hw_priv->workqueue,
201 					   &priv->multicast_start_work);
202 			priv->sta_asleep_mask |= bit;
203 			ap_printk(XRADIO_DBG_NIY, "%s STAs sleep: 0x%08X\n",
204 				__func__, bit);
205 		}
206 		break;
207 	case STA_NOTIFY_AWAKE:
208 		if (prev) {
209 			priv->sta_asleep_mask &= ~bit;
210 			priv->pspoll_mask &= ~bit;
211 			if (priv->tx_multicast && link_id &&
212 			    !priv->sta_asleep_mask)
213 				queue_work(hw_priv->workqueue,
214 					   &priv->multicast_stop_work);
215 			xradio_proc_wakeup(hw_priv);
216 			ap_printk(XRADIO_DBG_NIY, "%s STAs awake: 0x%08X\n",
217 				__func__, bit);
218 		}
219 		break;
220 	}
221 }
222 
xradio_sta_notify(struct ieee80211_hw * dev,struct ieee80211_vif * vif,enum sta_notify_cmd notify_cmd,struct ieee80211_sta * sta)223 void xradio_sta_notify(struct ieee80211_hw *dev,
224 		       struct ieee80211_vif *vif,
225 		       enum sta_notify_cmd notify_cmd,
226 		       struct ieee80211_sta *sta)
227 {
228 	struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
229 	struct xradio_sta_priv *sta_priv =
230 	    (struct xradio_sta_priv *)&sta->drv_priv;
231 
232 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
233 	if (!atomic_read(&priv->enabled)) {
234 		ap_printk(XRADIO_DBG_NIY, "%s vif(type=%d) is not enable!\n",
235 				__func__, vif->type);
236 		return ;
237 	}
238 
239 #ifdef P2P_MULTIVIF
240 	SYS_WARN(priv->if_id == XRWL_GENERIC_IF_ID);
241 #endif
242 	spin_lock_bh(&priv->ps_state_lock);
243 	__xradio_sta_notify(priv, notify_cmd, sta_priv->link_id);
244 	spin_unlock_bh(&priv->ps_state_lock);
245 }
246 
xradio_ps_notify(struct xradio_vif * priv,int link_id,bool ps)247 static void xradio_ps_notify(struct xradio_vif *priv, int link_id, bool ps)
248 {
249 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
250 
251 	if (link_id > MAX_STA_IN_AP_MODE) {
252 		ap_printk(XRADIO_DBG_WARN, "link_id is invalid=%d\n", link_id);
253 		return;
254 	}
255 
256 	ap_printk(XRADIO_DBG_NIY, "%s for LinkId: %d. STAs asleep: %.8X\n",
257 		  ps ? "Stop" : "Start", link_id, priv->sta_asleep_mask);
258 
259 	/* TODO:COMBO: __xradio_sta_notify changed. */
260 	__xradio_sta_notify(priv, ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE,
261 			    link_id);
262 }
263 
xradio_set_tim_impl(struct xradio_vif * priv,bool aid0_bit_set)264 static int xradio_set_tim_impl(struct xradio_vif *priv, bool aid0_bit_set)
265 {
266 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
267 	struct sk_buff *skb;
268 	struct wsm_update_ie update_ie = {
269 		.what = WSM_UPDATE_IE_BEACON,
270 		.count = 1,
271 	};
272 	u16 tim_offset, tim_length;
273 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
274 	ap_printk(XRADIO_DBG_MSG, "%s mcast: %s.\n", __func__,
275 		      aid0_bit_set ? "ena" : "dis");
276 
277 	skb = mac80211_beacon_get_tim(priv->hw, priv->vif, &tim_offset,
278 				&tim_length);
279 	if (!skb) {
280 		__xradio_flush(hw_priv, true, priv->if_id);
281 		return -ENOENT;
282 	}
283 
284 	if (tim_offset && tim_length >= 6) {
285 		/* Ignore DTIM count from mac80211:
286 		 * firmware handles DTIM internally. */
287 		skb->data[tim_offset + 2] = 0;
288 
289 		/* Set/reset aid0 bit */
290 		if (aid0_bit_set)
291 			skb->data[tim_offset + 4] |= 1;
292 		else
293 			skb->data[tim_offset + 4] &= ~1;
294 	}
295 
296 	update_ie.ies = &skb->data[tim_offset];
297 	update_ie.length = tim_length;
298 	/*filter same tim info*/
299 	if (memcmp(priv->last_tim, update_ie.ies, tim_length)) {
300 		SYS_WARN(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
301 		memcpy(priv->last_tim, update_ie.ies, tim_length);
302 		ap_printk(XRADIO_DBG_MSG, "%02x %02x %02x %02x %02x %02x\n",
303 			  update_ie.ies[0], update_ie.ies[1], update_ie.ies[2],
304 			  update_ie.ies[3], update_ie.ies[4], update_ie.ies[5]);
305 	}
306 
307 	dev_kfree_skb(skb);
308 
309 	return 0;
310 }
311 
xradio_set_tim_work(struct work_struct * work)312 void xradio_set_tim_work(struct work_struct *work)
313 {
314 	struct xradio_vif *priv =
315 	    container_of(work, struct xradio_vif, set_tim_work);
316 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
317 
318 	xradio_set_tim_impl(priv, priv->aid0_bit_set);
319 }
320 
xradio_set_tim(struct ieee80211_hw * dev,struct ieee80211_sta * sta,bool set)321 int xradio_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
322 		   bool set)
323 {
324 	struct xradio_sta_priv *sta_priv =
325 	    (struct xradio_sta_priv *)&sta->drv_priv;
326 	struct xradio_vif *priv = sta_priv->priv;
327 
328 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
329 	if (!atomic_read(&priv->enabled)) {
330 		ap_printk(XRADIO_DBG_WARN, "%s vif is not enable!\n", __func__);
331 		return 0;
332 	}
333 
334 #ifdef P2P_MULTIVIF
335 	SYS_WARN(priv->if_id == XRWL_GENERIC_IF_ID);
336 #endif
337 	SYS_WARN(priv->mode != NL80211_IFTYPE_AP);
338 	queue_work(priv->hw_priv->workqueue, &priv->set_tim_work);
339 	return 0;
340 }
341 
xradio_set_cts_work(struct work_struct * work)342 void xradio_set_cts_work(struct work_struct *work)
343 {
344 	struct xradio_vif *priv =
345 	    container_of(work, struct xradio_vif, set_cts_work.work);
346 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
347 	u8 erp_ie[3] = { WLAN_EID_ERP_INFO, 0x1, 0 };
348 	struct wsm_update_ie update_ie = {
349 		.what = WSM_UPDATE_IE_BEACON,
350 		.count = 1,
351 		.ies = erp_ie,
352 		.length = 3,
353 	};
354 	u32 erp_info;
355 	__le32 use_cts_prot;
356 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
357 
358 	down(&hw_priv->conf_lock);
359 	erp_info = priv->erp_info;
360 	up(&hw_priv->conf_lock);
361 	use_cts_prot = (erp_info & WLAN_ERP_USE_PROTECTION) ?
362 			__cpu_to_le32(1) : 0;
363 
364 	erp_ie[ERP_INFO_BYTE_OFFSET] = erp_info;
365 
366 	ap_printk(XRADIO_DBG_MSG, "ERP information 0x%x\n", erp_info);
367 
368 	/* TODO:COMBO: If 2 interfaces are on the same channel they share
369 	   the same ERP values */
370 	SYS_WARN(wsm_write_mib(hw_priv, WSM_MIB_ID_NON_ERP_PROTECTION,
371 			       &use_cts_prot, sizeof(use_cts_prot),
372 			       priv->if_id));
373 	/* If STA Mode update_ie is not required */
374 	if (priv->mode != NL80211_IFTYPE_STATION &&
375 		priv->mode != NL80211_IFTYPE_P2P_DEVICE) {
376 		SYS_WARN(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
377 	}
378 
379 	return;
380 }
381 
xradio_set_btcoexinfo(struct xradio_vif * priv)382 static int xradio_set_btcoexinfo(struct xradio_vif *priv)
383 {
384 	struct wsm_override_internal_txrate arg;
385 	int ret = 0;
386 
387 #ifdef SUPPORT_HT40
388 
389 	u8 rateIndex = 0x0;
390 
391 #endif
392 
393 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
394 
395 	if (priv->mode == NL80211_IFTYPE_STATION ||
396 		priv->mode == NL80211_IFTYPE_P2P_DEVICE) {
397 		/* Plumb PSPOLL and NULL template */
398 		SYS_WARN(xradio_upload_pspoll(priv));
399 		SYS_WARN(xradio_upload_null(priv));
400 	} else {
401 		return 0;
402 	}
403 
404 	memset(&arg, 0, sizeof(struct wsm_override_internal_txrate));
405 
406 	if (!priv->vif->p2p) {
407 		/* STATION mode */
408 		if (priv->bss_params.operationalRateSet & ~0xF) {
409 			ap_printk(XRADIO_DBG_NIY, "STA has ERP rates\n");
410 			/* G or BG mode */
411 
412 #ifdef SUPPORT_HT40
413 
414 			rateIndex =
415 			(__ffs(priv->bss_params.operationalRateSet & ~0xF));
416 
417 			arg.internalTxRateEntry =
418 				xradio_get_rate_entry(priv->hw_priv, 0, 0,
419 								rateIndex);
420 
421 #else
422 
423 			arg.internalTxRate =
424 			    (__ffs(priv->bss_params.operationalRateSet & ~0xF));
425 
426 #endif
427 		} else {
428 			ap_printk(XRADIO_DBG_NIY, "STA has non ERP rates\n");
429 			/* B only mode */
430 
431 #ifdef SUPPORT_HT40
432 
433 			rateIndex =
434 			(__ffs(priv->association_mode.basicRateSet));
435 
436 			arg.internalTxRateEntry =
437 				xradio_get_rate_entry(priv->hw_priv, 0, 0,
438 								rateIndex);
439 
440 #else
441 
442 			arg.internalTxRate =
443 			    (__ffs(priv->association_mode.basicRateSet));
444 
445 #endif
446 		}
447 
448 #ifdef SUPPORT_HT40
449 
450 		rateIndex = (__ffs(priv->association_mode.basicRateSet));
451 		arg.nonErpInterTxRateEntry =
452 			xradio_get_rate_entry(priv->hw_priv, 0, 0, rateIndex);
453 
454 #else
455 		arg.nonErpInternalTxRate =
456 		    (__ffs(priv->association_mode.basicRateSet));
457 
458 #endif
459 	} else {
460 		/* P2P mode */
461 
462 #ifdef SUPPORT_HT40
463 
464 		rateIndex = (__ffs(priv->bss_params.operationalRateSet & ~0xF));
465 
466 		arg.internalTxRateEntry =
467 			xradio_get_rate_entry(priv->hw_priv, 0, 0, rateIndex);
468 
469 		arg.nonErpInterTxRateEntry = arg.internalTxRateEntry;
470 
471 #else
472 
473 		arg.internalTxRate =
474 		    (__ffs(priv->bss_params.operationalRateSet & ~0xF));
475 		arg.nonErpInternalTxRate =
476 		    (__ffs(priv->bss_params.operationalRateSet & ~0xF));
477 
478 #endif
479 
480 	}
481 
482 #ifdef SUPPORT_HT40
483 
484 	ap_printk(XRADIO_DBG_NIY, "[STA] BTCOEX_INFO" \
485 		"MODE %d, internalTxRateEntry : " \
486 		"0x%04x, nonErpInterTxRateEntry: 0x%04x\n",
487 		priv->mode, arg.internalTxRateEntry,
488 		arg.nonErpInterTxRateEntry);
489 
490 #else
491 
492 	ap_printk(XRADIO_DBG_NIY, "BTCOEX_INFO" "MODE %d, internalTxRate : %x, " \
493 		  "nonErpInternalTxRate: %x\n", priv->mode, arg.internalTxRate,
494 		  arg.nonErpInternalTxRate);
495 
496 #endif
497 
498 	ret = SYS_WARN(wsm_write_mib(xrwl_vifpriv_to_hwpriv(priv),
499 				     WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
500 				     &arg, sizeof(arg), priv->if_id));
501 
502 	return ret;
503 }
504 
xradio_bss_info_changed(struct ieee80211_hw * dev,struct ieee80211_vif * vif,struct ieee80211_bss_conf * info,u32 changed)505 void xradio_bss_info_changed(struct ieee80211_hw *dev,
506 			     struct ieee80211_vif *vif,
507 			     struct ieee80211_bss_conf *info, u32 changed)
508 {
509 	struct xradio_common *hw_priv = dev->priv;
510 	struct xradio_vif *priv = xrwl_get_vif_from_ieee80211(vif);
511 
512 	enum nl80211_channel_type chan_type = cfg80211_get_chandef_type(&info->chandef);
513 
514 	int suspend_lock_state;
515 
516 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
517 
518 	if (hw_priv->bh_error) {
519 		ap_printk(XRADIO_DBG_ERROR, "%s bh_error occurs, changed=0x%0x\n",
520 			__func__, changed);
521 		return;
522 	}
523 
524 #ifdef P2P_MULTIVIF
525 	if (priv->if_id == XRWL_GENERIC_IF_ID)
526 		return;
527 #endif
528 
529 	suspend_lock_state = atomic_cmpxchg(&hw_priv->suspend_lock_state,
530 								XRADIO_SUSPEND_LOCK_IDEL, XRADIO_SUSPEND_LOCK_OTHERS);
531 	if (suspend_lock_state == XRADIO_SUSPEND_LOCK_SUSPEND) {
532 		ap_printk(XRADIO_DBG_WARN,
533 			   "%s:refuse because of suspend\n", __func__);
534 		return;
535 	}
536 
537 	down(&hw_priv->conf_lock);
538 	atomic_set(&hw_priv->suspend_lock_state, XRADIO_SUSPEND_LOCK_IDEL);
539 
540 	/*We do somethings first which is not of priv.*/
541 	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
542 		spin_lock_bh(&hw_priv->tx_policy_cache.lock);
543 		/*TODO:COMBO: for now it's still handled per hw and kept
544 		 * in xradio_common */
545 #ifdef ENHANCE_ANTI_INTERFERE
546 		hw_priv->long_frame_max_tx_count  = 15;
547 		hw_priv->short_frame_max_tx_count = 15;
548 #else
549 		hw_priv->long_frame_max_tx_count  = info->retry_long;
550 		hw_priv->short_frame_max_tx_count =
551 				(info->retry_short < 0x0F ? info->retry_short : 0x0F);
552 #endif
553 
554 		hw_priv->hw->max_rate_tries = hw_priv->short_frame_max_tx_count;
555 		spin_unlock_bh(&hw_priv->tx_policy_cache.lock);
556 		ap_printk(XRADIO_DBG_NIY, "Retry limits: long=%d(), short=%d().\n",
557 			  hw_priv->short_frame_max_tx_count,
558 			  hw_priv->long_frame_max_tx_count);
559 		/* TBD: I think we don't need tx_policy_force_upload().
560 		 * Outdated policies will leave cache in a normal way. */
561 		/* SYS_WARN(tx_policy_force_upload(priv)); */
562 	}
563 
564 	/*We check priv before operation of priv.*/
565 	if (!atomic_read(&priv->enabled)) {
566 		if (changed & ~IEEE80211_CONF_CHANGE_RETRY_LIMITS)
567 			ap_printk(XRADIO_DBG_WARN, "%s vif(type=%d) is not enable!" \
568 					"changed=0x%x\n", __func__, vif->type, changed);
569 		up(&hw_priv->conf_lock);
570 		return ;
571 	}
572 
573 	if (changed & BSS_CHANGED_BSSID) {
574 #ifdef CONFIG_XRADIO_TESTMODE
575 		spin_lock_bh(&hw_priv->tsm_lock);
576 		if (hw_priv->tsm_info.sta_associated) {
577 			unsigned now = jiffies;
578 			hw_priv->tsm_info.sta_roamed = 1;
579 			if ((now - hw_priv->tsm_info.txconf_timestamp_vo) >
580 			    (now - hw_priv->tsm_info.rx_timestamp_vo))
581 				hw_priv->tsm_info.use_rx_roaming = 1;
582 		} else {
583 			hw_priv->tsm_info.sta_associated = 1;
584 		}
585 		spin_unlock_bh(&hw_priv->tsm_lock);
586 #endif /*CONFIG_XRADIO_TESTMODE */
587 		memcpy(priv->bssid, info->bssid, ETH_ALEN);
588 		xradio_setup_mac_pvif(priv);
589 	}
590 
591 	/* TODO: BSS_CHANGED_IBSS */
592 	if (changed & BSS_CHANGED_ARP_FILTER) {
593 		struct wsm_arp_ipv4_filter filter = { 0 };
594 		int i;
595 		ap_printk(XRADIO_DBG_MSG,
596 			  "[STA] BSS_CHANGED_ARP_FILTER enabled: , cnt: %d\n",
597 			  info->arp_addr_cnt);
598 
599 		//if (info->arp_filter_enabled) {
600 		if (info->arp_addr_cnt) {
601 			if (vif->type == NL80211_IFTYPE_STATION ||
602 				vif->type == NL80211_IFTYPE_P2P_DEVICE)
603 				filter.enable =
604 				    (u32) XRADIO_ENABLE_ARP_FILTER_OFFLOAD;
605 			else if (priv->join_status == XRADIO_JOIN_STATUS_AP)
606 				filter.enable = (u32) (1 << 1);
607 			else
608 				filter.enable = 0;
609 		}
610 
611 		/* Currently only one IP address is supported by firmware.
612 		 * In case of more IPs arp filtering will be disabled. */
613 		if (info->arp_addr_cnt > 0 &&
614 		    info->arp_addr_cnt <= WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES) {
615 			for (i = 0; i < info->arp_addr_cnt; i++) {
616 				filter.ipv4Address[i] = info->arp_addr_list[i];
617 				ap_printk(XRADIO_DBG_NIY,
618 					  "[STA]addr[%d]: 0x%X\n", i,
619 					  filter.ipv4Address[i]);
620 			}
621 		} else
622 			filter.enable = 0;
623 
624 		if (filter.enable)
625 			xradio_set_arpreply(dev, vif);
626 
627 		priv->filter4.enable = filter.enable;
628 		ap_printk(XRADIO_DBG_NIY, "[STA]arp ip filter enable: %d\n",
629 			  __le32_to_cpu(filter.enable));
630 
631 		if (wsm_set_arp_ipv4_filter(hw_priv, &filter, priv->if_id))
632 			SYS_WARN(1);
633 
634 		if (filter.enable &&
635 		    (priv->join_status == XRADIO_JOIN_STATUS_STA)) {
636 			/* Firmware requires that value for this 1-byte field must
637 			 * be specified in units of 500us. Values above the 128ms
638 			 * threshold are not supported. */
639 			ap_printk(XRADIO_DBG_NIY,
640 				  "[STA]fastPsmIdle=%d, apPsmChange=%d\n",
641 				  priv->powersave_mode.fastPsmIdlePeriod,
642 				  priv->powersave_mode.apPsmChangePeriod);
643 
644 			if (priv->setbssparams_done) {
645 				int ret = 0;
646 				struct wsm_set_pm pm = priv->powersave_mode;
647 				if (priv->user_power_set_true)
648 					priv->powersave_mode.pmMode = priv->user_pm_mode;
649 				else if ((priv->power_set_true &&
650 					 ((priv->powersave_mode.pmMode == WSM_PSM_ACTIVE) ||
651 					 (priv->powersave_mode.pmMode == WSM_PSM_PS)))    ||
652 					 !priv->power_set_true)
653 					priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
654 
655 				priv->powersave_mode.pmMode |= WSM_PSM_IP_ALLOCATED;
656 				ret = xradio_set_pm(priv, &priv->powersave_mode);
657 				priv->powersave_mode.pmMode &= ~WSM_PSM_IP_ALLOCATED;
658 				if (ret)
659 					priv->powersave_mode = pm;
660 			} else {
661 				ap_printk(XRADIO_DBG_WARN, "arp_addr_cnt not clear at disconnecting,filter abnormal enable!!!\n");
662 			}
663 			priv->power_set_true = 0;
664 			priv->user_power_set_true = 0;
665 		}
666 	}
667 
668 #if IPV6_FILTERING
669 	if (changed & BSS_CHANGED_NDP_FILTER) {
670 		int i;
671 		struct wsm_ndp_ipv6_filter filter = { 0 };
672 		u16 *ipv6addr = NULL;
673 
674 		ap_printk(XRADIO_DBG_MSG,
675 			  "[STA] BSS_CHANGED_NDP_FILTER enabled: %d, cnt: %d\n",
676 			  info->ndp_filter_enabled, info->ndp_addr_cnt);
677 
678 		if (info->ndp_filter_enabled) {
679 			if (vif->type == NL80211_IFTYPE_STATION ||
680 				vif->type == NL80211_IFTYPE_P2P_DEVICE)
681 				filter.enable =
682 				    (u32) XRADIO_ENABLE_NDP_FILTER_OFFLOAD;
683 			else if (vif->type == NL80211_IFTYPE_AP)
684 				filter.enable = (u32) (1 << 1);
685 			else
686 				filter.enable = 0;
687 		}
688 
689 		/* Currently only one IP address is supported by firmware.
690 		 * In case of more IPs ndp filtering will be disabled. */
691 		if (info->ndp_addr_cnt > 0 &&
692 		    info->ndp_addr_cnt <= WSM_MAX_NDP_IP_ADDRTABLE_ENTRIES) {
693 			for (i = 0; i < info->ndp_addr_cnt; i++) {
694 				filter.ipv6Address[i] = info->ndp_addr_list[i];
695 				priv->filter6.ipv6Address[i] = filter.ipv6Address[i];
696 				ipv6addr = (u16 *)(&filter.ipv6Address[i]);
697 				ap_printk(XRADIO_DBG_MSG,
698 					  "[STA] ipv6 addr[%d]: %x:%x:%x:%x:%x:%x:%x:%x\n",
699 					  i, cpu_to_be16(*(ipv6addr + 0)),
700 					  cpu_to_be16(*(ipv6addr + 1)),
701 					  cpu_to_be16(*(ipv6addr + 2)),
702 					  cpu_to_be16(*(ipv6addr + 3)),
703 					  cpu_to_be16(*(ipv6addr + 4)),
704 					  cpu_to_be16(*(ipv6addr + 5)),
705 					  cpu_to_be16(*(ipv6addr + 6)),
706 					  cpu_to_be16(*(ipv6addr + 7)));
707 			}
708 		} else {
709 			filter.enable = 0;
710 			for (i = 0; i < info->ndp_addr_cnt; i++) {
711 				ipv6addr = (u16 *) (&info->ndp_addr_list[i]);
712 				ap_printk(XRADIO_DBG_MSG,
713 					  "[STA] ipv6 addr[%d]: %x:%x:%x:%x:%x:%x:%x:%x\n",
714 					  i, cpu_to_be16(*(ipv6addr + 0)),
715 					  cpu_to_be16(*(ipv6addr + 1)),
716 					  cpu_to_be16(*(ipv6addr + 2)),
717 					  cpu_to_be16(*(ipv6addr + 3)),
718 					  cpu_to_be16(*(ipv6addr + 4)),
719 					  cpu_to_be16(*(ipv6addr + 5)),
720 					  cpu_to_be16(*(ipv6addr + 6)),
721 					  cpu_to_be16(*(ipv6addr + 7)));
722 			}
723 		}
724 
725 		ap_printk(XRADIO_DBG_NIY, "[STA] ndp ip filter enable: %d\n",
726 			   __le32_to_cpu(filter.enable));
727 
728 		if (filter.enable)
729 			xradio_set_na(dev, vif);
730 
731 		priv->filter6.enable = filter.enable;
732 
733 		if (wsm_set_ndp_ipv6_filter(hw_priv, &filter, priv->if_id))
734 			SYS_WARN(1);
735 #if 0				/*Commented out to disable Power Save in IPv6 */
736 		if (filter.enable
737 		    && (priv->join_status == XRADIO_JOIN_STATUS_STA)
738 		    && (priv->vif->p2p)
739 		    && !(priv->firmware_ps_mode.pmMode & WSM_PSM_FAST_PS)) {
740 			if (priv->setbssparams_done) {
741 				int ret = 0;
742 				struct wsm_set_pm pm = priv->powersave_mode;
743 
744 				priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
745 				ret = xradio_set_pm(priv, &priv->powersave_mode);
746 				if (ret) {
747 					priv->powersave_mode = pm;
748 				}
749 			} else {
750 				priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
751 			}
752 		}
753 #endif
754 	}
755 #endif /*IPV6_FILTERING */
756 
757 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
758 		priv->enable_beacon = info->enable_beacon;
759 		ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_BEACON_ENABLED %s\n",
760 			priv->enable_beacon ? "enable" : "disable");
761 	}
762 
763 	if (changed & BSS_CHANGED_BEACON) {
764 		ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_BEACON(enable=%d)\n",
765 			priv->enable_beacon);
766 		if (priv->enable_beacon) {
767 #ifdef HIDDEN_SSID
768 			if (priv->join_status != XRADIO_JOIN_STATUS_AP) {
769 				priv->hidden_ssid = info->hidden_ssid;
770 				priv->ssid_length = info->ssid_len;
771 				ap_printk(XRADIO_DBG_NIY, "hidden_ssid=%d, ssid_len=%zu\n",
772 					  info->hidden_ssid, info->ssid_len);
773 				if (info->ssid_len) {
774 					memcpy(priv->ssid, info->ssid, info->ssid_len);
775 					ap_printk(XRADIO_DBG_NIY, "ssid=%s\n", info->ssid);
776 				}
777 			} else
778 				ap_printk(XRADIO_DBG_NIY, "priv->join_status=%d\n",
779 					  priv->join_status);
780 #endif
781 			SYS_WARN(xradio_upload_beacon(priv));
782 			SYS_WARN(xradio_update_beaconing(priv));
783 		}
784 	}
785 
786 	if (changed & BSS_CHANGED_BEACON_INT) {
787 		ap_printk(XRADIO_DBG_NIY, "CHANGED_BEACON_INT\n");
788 		/* Restart AP only when connected */
789 		if (priv->join_status == XRADIO_JOIN_STATUS_AP)
790 			SYS_WARN(xradio_update_beaconing(priv));
791 	}
792 
793 
794 	if (changed & BSS_CHANGED_ASSOC) {
795 		wsm_lock_tx(hw_priv);
796 		priv->wep_default_key_id = -1;
797 		wsm_unlock_tx(hw_priv);
798 
799 		if (!info->assoc /* && !info->ibss_joined */) {
800 			priv->cqm_link_loss_count = XRADIO_LINK_LOSS_THOLD_DEF;
801 			priv->cqm_beacon_loss_count = XRADIO_BSS_LOSS_THOLD_DEF;
802 			priv->cqm_tx_failure_thold = 0;
803 		}
804 		priv->cqm_tx_failure_count = 0;
805 	}
806 
807 	if (changed &
808 	    (BSS_CHANGED_ASSOC        |
809 	     BSS_CHANGED_BASIC_RATES  |
810 	     BSS_CHANGED_ERP_PREAMBLE |
811 	     BSS_CHANGED_HT           |
812 	     BSS_CHANGED_ERP_SLOT)) {
813 		int is_combo = 0;
814 		int i;
815 		struct xradio_vif *tmp_priv;
816 		ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_ASSOC.\n");
817 		/*Driver is already do unjoin.*/
818 		if (priv->if_id == 0 && priv->vif->type == NL80211_IFTYPE_STATION &&
819 			priv->join_status == XRADIO_JOIN_STATUS_PASSIVE) {
820 			changed &= ~BSS_CHANGED_ASSOC;
821 			ap_printk(XRADIO_DBG_WARN, "BSS_CHANGED_ASSOC but driver is unjoined.\n");
822 			mac80211_connection_loss(priv->vif);
823 		}
824 		/* TODO: ibss_joined */
825 		if (info->assoc && priv->join_status != XRADIO_JOIN_STATUS_PASSIVE) {
826 			struct ieee80211_sta *sta = NULL;
827 
828 #ifdef SUPPORT_HT40
829 			struct phy_mode_cfg PhyModeCfg;
830 #endif
831 			if (info->dtim_period)
832 				priv->join_dtim_period = info->dtim_period;
833 			priv->beacon_int = info->beacon_int;
834 
835 			/* Associated: kill join timeout */
836 			cancel_delayed_work(&priv->join_timeout);
837 
838 			rcu_read_lock();
839 			if (info->bssid)
840 				sta = mac80211_find_sta(vif, info->bssid);
841 			if (sta) {
842 				/* TODO:COMBO:Change this once
843 				 * mac80211 changes are available */
844 				SYS_BUG(!hw_priv->channel);
845 				hw_priv->ht_info.ht_cap = sta->ht_cap;
846 				priv->bss_params.operationalRateSet =
847 				  __cpu_to_le32(xradio_rate_mask_to_wsm(hw_priv,
848 						sta->supp_rates[hw_priv->channel->band]));
849 				hw_priv->ht_info.channel_type   = chan_type;
850 				hw_priv->ht_info.operation_mode = info->ht_operation_mode;
851 				priv->oper_rates = sta->supp_rates[hw_priv->channel->band];
852 			} else {
853 				ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_ASSOC no sta.\n");
854 				memset(&hw_priv->ht_info, 0, sizeof(hw_priv->ht_info));
855 				priv->bss_params.operationalRateSet = -1;
856 				priv->oper_rates = -1;
857 			}
858 			rcu_read_unlock();
859 			priv->htcap = (sta && xradio_is_ht(&hw_priv->ht_info));
860 			xradio_for_each_vif(hw_priv, tmp_priv, i) {
861 #ifdef P2P_MULTIVIF
862 				if ((i == (XRWL_MAX_VIFS - 1)) || !tmp_priv)
863 #else
864 				if (!tmp_priv)
865 #endif
866 					continue;
867 				if (tmp_priv->join_status >= XRADIO_JOIN_STATUS_STA)
868 					is_combo++;
869 			}
870 
871 			if (is_combo > 1) {
872 				hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
873 				hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
874 				ap_printk(XRADIO_DBG_WARN, "%sASSOC is_combo %d\n",
875 					 (priv->join_status == XRADIO_JOIN_STATUS_STA) ?
876 					  "[STA] " : "", hw_priv->vif0_throttle);
877 			} else if ((priv->join_status == XRADIO_JOIN_STATUS_STA)
878 				   && priv->htcap) {
879 				hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
880 				hw_priv->vif1_throttle = XRWL_HOST_VIF1_11N_THROTTLE;
881 				ap_printk(XRADIO_DBG_WARN, "[STA] ASSOC HTCAP 11N %d\n",
882 					  hw_priv->vif0_throttle);
883 			} else {
884 				hw_priv->vif0_throttle = XRWL_HOST_VIF0_11BG_THROTTLE;
885 				hw_priv->vif1_throttle = XRWL_HOST_VIF1_11BG_THROTTLE;
886 				ap_printk(XRADIO_DBG_WARN, "ASSOC not_combo 11BG %d\n",
887 					  hw_priv->vif0_throttle);
888 			}
889 
890 			if (sta) {
891 
892 #ifdef SUPPORT_HT40
893 
894 				__le32 ht_prot = 0;
895 
896 				if (hw_priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)
897 					ht_prot |= cpu_to_le32(WSM_NON_GREENFIELD_STA);
898 
899 				ht_prot |= cpu_to_le32((hw_priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) << 2);
900 
901 				ap_printk(XRADIO_DBG_WARN, "[HT40][%s]" \
902 					"[ht_prot:0x%08x][HtProtMode:0x%04x]" \
903 					"[Green:0x%04x]",
904 					__func__, ht_prot,
905 					hw_priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION,
906 					hw_priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
907 
908 				WARN_ON(wsm_write_mib(hw_priv,
909 					WSM_MID_ID_SET_HT_PROTECTION,
910 					&ht_prot, sizeof(ht_prot), priv->if_id));
911 
912 #else
913 
914 				__le32 val = 0;
915 				if (hw_priv->ht_info.operation_mode &
916 				    IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) {
917 					ap_printk(XRADIO_DBG_NIY, "[STA] Non-GF STA present\n");
918 					/* Non Green field capable STA */
919 					val = __cpu_to_le32(BIT(1));
920 				}
921 				SYS_WARN(wsm_write_mib(hw_priv, WSM_MID_ID_SET_HT_PROTECTION,
922 						       &val, sizeof(val), priv->if_id));
923 
924 #endif
925 
926 			}
927 
928 #ifdef SUPPORT_HT40
929 
930 			PhyModeCfg.BandCfg = hw_priv->channel->band;
931 
932 			if (PhyModeCfg.BandCfg == NL80211_BAND_5GHZ)
933 				PhyModeCfg.ModemFlags = (MODEM_F_A_OFDM|MODEM_F_N_OFDM);
934 			else
935 				PhyModeCfg.ModemFlags = (MODEM_F_B_DSSS|MODEM_F_A_OFDM|MODEM_F_N_OFDM);
936 
937 			if (chan_type == NL80211_CHAN_HT40MINUS) {
938 				PhyModeCfg.ChWidthCfg = CHAN_WIDTH_40MHz;
939 				PhyModeCfg.PriChCfg   = PRIMARY_CH_1ST;
940 			} else if (chan_type == NL80211_CHAN_HT40PLUS) {
941 				PhyModeCfg.ChWidthCfg = CHAN_WIDTH_40MHz;
942 				PhyModeCfg.PriChCfg   = PRIMARY_CH_2ND;
943 			} else {
944 				PhyModeCfg.ChWidthCfg = CHAN_WIDTH_20MHz;
945 				PhyModeCfg.PriChCfg   = PRIMARY_CH_1ST;
946 			}
947 
948 			if (chan_type == NL80211_CHAN_NO_HT) {
949 				PhyModeCfg.ModemFlags &= ~(MODEM_F_N_OFDM);
950 				PhyModeCfg.SGI_Enable = false;
951 				PhyModeCfg.GF_Enable = false;
952 			} else {
953 				PhyModeCfg.SGI_Enable = xradio_ht_ShortGI(&hw_priv->ht_info);
954 				PhyModeCfg.GF_Enable  = xradio_ht_greenfield(&hw_priv->ht_info);
955 			}
956 
957 			PhyModeCfg.STBC_Enable = false;
958 			PhyModeCfg.PreambleCfg = info->use_short_preamble ?
959 				WSM_JOIN_PREAMBLE_SHORT :
960 				WSM_JOIN_PREAMBLE_LONG;
961 
962 			priv->association_mode.PhyModeCfg = PhyModeCfg;
963 
964 			priv->association_mode.flags =
965 				WSM_ASSOCIATION_MODE_USE_PHY_MODE_CFG |
966 				WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET |
967 				WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING;
968 
969 #else
970 			priv->association_mode.greenfieldMode =
971 			    xradio_ht_greenfield(&hw_priv->ht_info);
972 			priv->association_mode.flags =
973 			    WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES |
974 			    WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE |
975 			    WSM_ASSOCIATION_MODE_USE_HT_MODE |
976 			    WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET |
977 			    WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING;
978 
979 			priv->association_mode.preambleType =
980 			  (info->use_short_preamble ? WSM_JOIN_PREAMBLE_SHORT :
981 			   WSM_JOIN_PREAMBLE_LONG);
982 
983 #endif
984 
985 			priv->association_mode.basicRateSet =
986 			    __cpu_to_le32(xradio_rate_mask_to_wsm(hw_priv,
987 					  info->basic_rates));
988 			priv->base_rates = info->basic_rates;
989 			priv->association_mode.mpduStartSpacing =
990 			    xradio_ht_ampdu_density(&hw_priv->ht_info);
991 
992 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
993 			priv->cqm_beacon_loss_count = 0; //info->cqm_beacon_miss_thold;
994 			priv->cqm_tx_failure_thold = 0; //info->cqm_tx_fail_thold;
995 			priv->cqm_tx_failure_count = 0;
996 			cancel_delayed_work_sync(&priv->bss_loss_work);
997 			cancel_delayed_work_sync(&priv->connection_loss_work);
998 #endif /* CONFIG_XRADIO_USE_EXTENSIONS */
999 
1000 			priv->bss_params.beaconLostCount = (priv->cqm_beacon_loss_count ?
1001 			  priv->cqm_beacon_loss_count : priv->cqm_link_loss_count);
1002 
1003 			priv->bss_params.aid = info->aid;
1004 
1005 			if (priv->join_dtim_period < 1)
1006 				priv->join_dtim_period = 1;
1007 
1008 #ifdef SUPPORT_HT40
1009 
1010 			ap_printk(XRADIO_DBG_WARN, "[HT40][%s]"\
1011 				"[PhyModeCfg:0x%04x]\n"\
1012 				"[ModemFlags    :0x%08x]\n"\
1013 				"[ChWidthCfg    :0x%08x]\n"\
1014 				"[PriChCfg      :0x%08x]\n"\
1015 				"[BandCfg       :0x%08x]\n"\
1016 				"[STBC_Enable   :0x%08x]\n"\
1017 				"[PreambleCfg   :0x%08x]\n"\
1018 				"[SGI_Enable    :0x%08x]\n"\
1019 				"[GF_Enable     :0x%08x]\n",
1020 				__func__,
1021 				*(u16 *)&(priv->association_mode.PhyModeCfg),
1022 				priv->association_mode.PhyModeCfg.ModemFlags,
1023 				priv->association_mode.PhyModeCfg.ChWidthCfg,
1024 				priv->association_mode.PhyModeCfg.PriChCfg,
1025 				priv->association_mode.PhyModeCfg.BandCfg,
1026 				priv->association_mode.PhyModeCfg.STBC_Enable,
1027 				priv->association_mode.PhyModeCfg.PreambleCfg,
1028 				priv->association_mode.PhyModeCfg.SGI_Enable,
1029 				priv->association_mode.PhyModeCfg.GF_Enable);
1030 
1031 			ap_printk(XRADIO_DBG_MSG, "[STA] DTIM %d, "\
1032 				"interval: %d\n",
1033 				priv->join_dtim_period, priv->beacon_int);
1034 
1035 			ap_printk(XRADIO_DBG_MSG, "[STA] Preamble: %d, "\
1036 				"Greenfield: %d, Aid: %d, "\
1037 				"Rates: 0x%.8X, Basic: 0x%.8X\n",
1038 				priv->association_mode.PhyModeCfg.PreambleCfg,
1039 				priv->association_mode.PhyModeCfg.GF_Enable,
1040 				priv->bss_params.aid,
1041 				priv->bss_params.operationalRateSet,
1042 				priv->association_mode.basicRateSet);
1043 
1044 #else
1045 
1046 			ap_printk(XRADIO_DBG_MSG, "[STA] DTIM %d, interval: %d\n",
1047 				  priv->join_dtim_period, priv->beacon_int);
1048 			ap_printk(XRADIO_DBG_MSG, "[STA] Preamble: %d, " \
1049 				  "Greenfield: %d, Aid: %d, " \
1050 				  "Rates: 0x%.8X, Basic: 0x%.8X\n",
1051 				  priv->association_mode.preambleType,
1052 				  priv->association_mode.greenfieldMode,
1053 				  priv->bss_params.aid,
1054 				  priv->bss_params.operationalRateSet,
1055 				  priv->association_mode.basicRateSet);
1056 
1057 #endif
1058 
1059 			SYS_WARN(wsm_set_association_mode(hw_priv,
1060 				 &priv->association_mode, priv->if_id));
1061 			SYS_WARN(wsm_keep_alive_period(hw_priv,
1062 						       XRADIO_KEEP_ALIVE_PERIOD /* sec */,
1063 						       priv->if_id));
1064 			SYS_WARN(wsm_set_bss_params(hw_priv,
1065 				 &priv->bss_params, priv->if_id));
1066 			priv->setbssparams_done = true;
1067 #ifdef XRADIO_USE_LONG_DTIM_PERIOD
1068 			{
1069 				int join_dtim_period_extend;
1070 				if (priv->join_dtim_period <= 3) {
1071 					join_dtim_period_extend = priv->join_dtim_period * 3;
1072 				} else if (priv->join_dtim_period <= 5) {
1073 					join_dtim_period_extend = priv->join_dtim_period * 2;
1074 				} else {
1075 					join_dtim_period_extend = priv->join_dtim_period;
1076 				}
1077 				SYS_WARN(wsm_set_beacon_wakeup_period(hw_priv,
1078 					((priv->beacon_int * join_dtim_period_extend) >
1079 					MAX_BEACON_SKIP_TIME_MS ?
1080 					1 : join_dtim_period_extend), 0, priv->if_id));
1081 			}
1082 #else
1083 			SYS_WARN(wsm_set_beacon_wakeup_period(hw_priv,
1084 				 ((priv->beacon_int * priv->join_dtim_period) >
1085 				 MAX_BEACON_SKIP_TIME_MS ?
1086 				 1 : priv->join_dtim_period), 0, priv->if_id));
1087 #endif
1088 			if (priv->htcap) {
1089 				wsm_lock_tx(hw_priv);
1090 				/* Statically enabling block ack for TX/RX */
1091 				SYS_WARN(wsm_set_block_ack_policy(hw_priv,
1092 					 hw_priv->ba_tid_mask, hw_priv->ba_tid_mask,
1093 					 priv->if_id));
1094 				wsm_unlock_tx(hw_priv);
1095 			}
1096 			if (priv->filter4.enable || !(priv->powersave_mode.pmMode&WSM_PSM_PS)) {
1097 				xradio_set_pm(priv, &priv->powersave_mode);
1098 			}
1099 			if (priv->vif->p2p) {
1100 				ap_printk(XRADIO_DBG_NIY,
1101 					  "[STA] Setting p2p powersave configuration.\n");
1102 				SYS_WARN(wsm_set_p2p_ps_modeinfo(hw_priv,
1103 					 &priv->p2p_ps_modeinfo, priv->if_id));
1104 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
1105 				xradio_notify_noa(priv, XRADIO_NOA_NOTIFICATION_DELAY);
1106 #endif
1107 			}
1108 
1109 			if (priv->mode == NL80211_IFTYPE_STATION ||
1110 				priv->mode == NL80211_IFTYPE_P2P_DEVICE)
1111 				SYS_WARN(xradio_upload_qosnull(priv));
1112 
1113 			if (hw_priv->is_BT_Present)
1114 				SYS_WARN(xradio_set_btcoexinfo(priv));
1115 #if 0
1116 			/* It's better to override internal TX rete; otherwise
1117 			 * device sends RTS at too high rate. However device
1118 			 * can't receive CTS at 1 and 2 Mbps. Well, 5.5 is a
1119 			 * good choice for RTS/CTS, but that means PS poll
1120 			 * will be sent at the same rate - impact on link
1121 			 * budget. Not sure what is better.. */
1122 
1123 			/* Update: internal rate selection algorythm is not
1124 			 * bad: if device is not receiving CTS at high rate,
1125 			 * it drops RTS rate.
1126 			 * So, conclusion: if-0 the code. Keep code just for
1127 			 * information:
1128 			 * Do not touch WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE! */
1129 
1130 			/* ~3 is a bug in device: RTS/CTS is not working at
1131 			 * low rates */
1132 			__le32 internal_tx_rate =
1133 			    __cpu_to_le32(__ffs(priv->association_mode.basicRateSet & ~3));
1134 			SYS_WARN(wsm_write_mib(priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE,
1135 				 &internal_tx_rate, sizeof(internal_tx_rate)));
1136 #endif
1137 		} else {
1138 			ap_printk(XRADIO_DBG_NIY, "BSS_CHANGED_ASSOC not assoc, change=0x%08x.\n", changed);
1139 			memset(&priv->association_mode, 0, sizeof(priv->association_mode));
1140 			memset(&priv->bss_params, 0, sizeof(priv->bss_params));
1141 			priv->base_rates = -1;
1142 			priv->oper_rates = -1;
1143 		}
1144 	}
1145 	if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT)) {
1146 		u32 prev_erp_info = priv->erp_info;
1147 		if (priv->join_status == XRADIO_JOIN_STATUS_AP) {
1148 			if (info->use_cts_prot)
1149 				priv->erp_info |= WLAN_ERP_USE_PROTECTION;
1150 			else if (!(prev_erp_info & WLAN_ERP_NON_ERP_PRESENT))
1151 				priv->erp_info &= ~WLAN_ERP_USE_PROTECTION;
1152 
1153 			if (prev_erp_info != priv->erp_info)
1154 				queue_delayed_work(hw_priv->workqueue,
1155 						   &priv->set_cts_work, 0*HZ);
1156 		}
1157 	}
1158 
1159 	if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_SLOT)) {
1160 		__le32 slot_time = info->use_short_slot ?
1161 				   __cpu_to_le32(9) : __cpu_to_le32(20);
1162 		ap_printk(XRADIO_DBG_MSG, "[STA] Slot time :%d us.\n",
1163 			  __le32_to_cpu(slot_time));
1164 		SYS_WARN(wsm_write_mib(hw_priv, WSM_MIB_ID_DOT11_SLOT_TIME,
1165 				       &slot_time, sizeof(slot_time), priv->if_id));
1166 	}
1167 	if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_CQM)) {
1168 		struct wsm_rcpi_rssi_threshold threshold = {
1169 			.rollingAverageCount = 8,
1170 		};
1171 
1172 #if 0
1173 		/* For verification purposes */
1174 		info->cqm_rssi_thold = -50;
1175 		info->cqm_rssi_hyst = 4;
1176 #endif /* 0 */
1177 
1178 		ap_printk(XRADIO_DBG_NIY,
1179 			  "[CQM] RSSI threshold subscribe: %d(+-%d)\n",
1180 			  info->cqm_rssi_thold, info->cqm_rssi_hyst);
1181 
1182 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
1183 		//ap_printk(XRADIO_DBG_NIY, "[CQM] Beacon loss subscribe: %d\n",
1184 			  //info->cqm_beacon_miss_thold);
1185 		//ap_printk(XRADIO_DBG_NIY, "[CQM] TX failure subscribe: %d\n",
1186 			  //info->cqm_tx_fail_thold);
1187 		priv->cqm_rssi_thold = info->cqm_rssi_thold;
1188 		priv->cqm_rssi_hyst  = info->cqm_rssi_hyst;
1189 #endif /* CONFIG_XRADIO_USE_EXTENSIONS */
1190 
1191 		if (info->cqm_rssi_thold || info->cqm_rssi_hyst) {
1192 			/* RSSI subscription enabled */
1193 			/* TODO: It's not a correct way of setting threshold.
1194 			 * Upper and lower must be set equal here and adjusted
1195 			 * in callback. However current implementation is much
1196 			 * more relaible and stable. */
1197 			if (priv->cqm_use_rssi) {
1198 				threshold.upperThreshold = info->cqm_rssi_thold +
1199 							   info->cqm_rssi_hyst;
1200 				threshold.lowerThreshold = info->cqm_rssi_thold;
1201 			} else {
1202 				/* convert RSSI to RCPI, RCPI = (RSSI + 110) * 2 */
1203 				threshold.upperThreshold = (info->cqm_rssi_thold +
1204 							    info->cqm_rssi_hyst + 110)<<1;
1205 				threshold.lowerThreshold = (info->cqm_rssi_thold + 110)<<1;
1206 			}
1207 			threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE;
1208 		} else {
1209 			/* There is a bug in FW, see sta.c. We have to enable
1210 			 * dummy subscription to get correct RSSI values. */
1211 			threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE |
1212 						  WSM_RCPI_RSSI_DONT_USE_UPPER   |
1213 						  WSM_RCPI_RSSI_DONT_USE_LOWER;
1214 		}
1215 		SYS_WARN(wsm_set_rcpi_rssi_threshold(hw_priv, &threshold, priv->if_id));
1216 
1217 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
1218 #if 0
1219 		//priv->cqm_tx_failure_thold = info->cqm_tx_fail_thold;
1220 		priv->cqm_tx_failure_count = 0;
1221 		if (priv->cqm_beacon_loss_count != info->cqm_beacon_miss_thold) {
1222 			priv->cqm_beacon_loss_count = info->cqm_beacon_miss_thold;
1223 			priv->bss_params.beaconLostCount = (priv->cqm_beacon_loss_count ?
1224 			  priv->cqm_beacon_loss_count : priv->cqm_link_loss_count);
1225 			/* Make sure we are associated before sending
1226 			 * set_bss_params to firmware */
1227 			if (priv->bss_params.aid) {
1228 				SYS_WARN(wsm_set_bss_params(hw_priv,
1229 					 &priv->bss_params, priv->if_id));
1230 				priv->setbssparams_done = true;
1231 			}
1232 		}
1233 #endif
1234 #endif /* CONFIG_XRADIO_USE_EXTENSIONS */
1235 	}
1236 
1237 	if (changed & BSS_CHANGED_PS) {
1238 		//if (info->ps_enabled == false)
1239 		//if ((dev->conf.flags & IEEE80211_CONF_PS) == 0)
1240 		if (vif->bss_conf.ps == false)
1241 			priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
1242 		//else if (info->dynamic_ps_timeout <= 0)
1243 		else if (dev->conf.dynamic_ps_timeout <= 0)
1244 			priv->powersave_mode.pmMode = WSM_PSM_PS;
1245 		else
1246 			priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
1247 
1248 		ap_printk(XRADIO_DBG_MSG, "[STA] Aid: %d, Joined: %s, Powersave: %s\n",
1249 		   priv->bss_params.aid,
1250 		   priv->join_status == XRADIO_JOIN_STATUS_STA ? "yes" : "no",
1251 		  (priv->powersave_mode.pmMode == WSM_PSM_ACTIVE ? "WSM_PSM_ACTIVE" :
1252 		   priv->powersave_mode.pmMode == WSM_PSM_PS ? "WSM_PSM_PS" :
1253 		   priv->powersave_mode.pmMode == WSM_PSM_FAST_PS ? "WSM_PSM_FAST_PS" :
1254 						  "UNKNOWN"));
1255 
1256 		/* Firmware requires that value for this 1-byte field must
1257 		 * be specified in units of 500us. Values above the 128ms
1258 		 * threshold are not supported. */
1259 		if (dev->conf.dynamic_ps_timeout >= 0x80)
1260 			priv->powersave_mode.fastPsmIdlePeriod = 0xFF;
1261 		else
1262 			priv->powersave_mode.fastPsmIdlePeriod =
1263 					     dev->conf.dynamic_ps_timeout << 1;
1264 		ap_printk(XRADIO_DBG_NIY,
1265 			  "[STA]CHANGED_PS fastPsmIdle=%d, apPsmChange=%d\n",
1266 			  priv->powersave_mode.fastPsmIdlePeriod,
1267 			  priv->powersave_mode.apPsmChangePeriod);
1268 
1269 		if (priv->join_status == XRADIO_JOIN_STATUS_STA
1270 		    && priv->bss_params.aid
1271 		    && priv->setbssparams_done && priv->filter4.enable)
1272 			xradio_set_pm(priv, &priv->powersave_mode);
1273 		else
1274 			priv->power_set_true = 1;
1275 	}
1276 
1277 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
1278 	if (changed & BSS_CHANGED_P2P_PS) {
1279 		struct wsm_p2p_ps_modeinfo *modeinfo;
1280 		modeinfo = &priv->p2p_ps_modeinfo;
1281 		ap_printk(XRADIO_DBG_NIY, "[AP] BSS_CHANGED_P2P_PS\n");
1282 #if 0
1283 		ap_printk(XRADIO_DBG_NIY,
1284 			  "[AP] Legacy PS: %d for AID %d in %d mode.\n",
1285 			  info->p2p_ps.legacy_ps, priv->bss_params.aid,
1286 			  priv->join_status);
1287 
1288 		if (info->p2p_ps.legacy_ps >= 0) {
1289 			if (info->p2p_ps.legacy_ps > 0)
1290 				priv->powersave_mode.pmMode = WSM_PSM_PS;
1291 			else
1292 				priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
1293 
1294 			if (info->p2p_ps.ctwindow && info->p2p_ps.opp_ps)
1295 				priv->powersave_mode.pmMode = WSM_PSM_PS;
1296 			if (priv->join_status == XRADIO_JOIN_STATUS_STA)
1297 				xradio_set_pm(priv, &priv->powersave_mode);
1298 		}
1299 
1300 		ap_printk(XRADIO_DBG_MSG, "[AP] CTWindow: %d\n",
1301 			  info->p2p_ps.ctwindow);
1302 		if (info->p2p_ps.ctwindow >= 128)
1303 			modeinfo->oppPsCTWindow = 127;
1304 		else if (info->p2p_ps.ctwindow >= 0)
1305 			modeinfo->oppPsCTWindow = info->p2p_ps.ctwindow;
1306 
1307 		ap_printk(XRADIO_DBG_MSG, "[AP] Opportunistic: %d\n",
1308 			  info->p2p_ps.opp_ps);
1309 		switch (info->p2p_ps.opp_ps) {
1310 		case 0:
1311 			modeinfo->oppPsCTWindow &= ~(BIT(7));
1312 			break;
1313 		case 1:
1314 			modeinfo->oppPsCTWindow |= BIT(7);
1315 			break;
1316 		default:
1317 			break;
1318 		}
1319 
1320 		ap_printk(XRADIO_DBG_MSG, "[AP] NOA: %d, %d, %d, %d\n",
1321 			  info->p2p_ps.count, info->p2p_ps.start,
1322 			  info->p2p_ps.duration, info->p2p_ps.interval);
1323 		/* Notice of Absence */
1324 		modeinfo->count = info->p2p_ps.count;
1325 
1326 		if (info->p2p_ps.count) {
1327 			/* In case P2P_GO we need some extra time to be sure
1328 			 * we will update beacon/probe_resp IEs correctly */
1329 #define NOA_DELAY_START_MS	300
1330 			if (priv->join_status == XRADIO_JOIN_STATUS_AP)
1331 				modeinfo->startTime =
1332 				    __cpu_to_le32(info->p2p_ps.start + NOA_DELAY_START_MS);
1333 			else
1334 				modeinfo->startTime = __cpu_to_le32(info->p2p_ps.start);
1335 			modeinfo->duration    = __cpu_to_le32(info->p2p_ps.duration);
1336 			modeinfo->interval    = __cpu_to_le32(info->p2p_ps.interval);
1337 			modeinfo->dtimCount   = 1;
1338 			modeinfo->reserved    = 0;
1339 		} else {
1340 			modeinfo->dtimCount = 0;
1341 			modeinfo->startTime = 0;
1342 			modeinfo->reserved  = 0;
1343 			modeinfo->duration  = 0;
1344 			modeinfo->interval  = 0;
1345 		}
1346 #endif
1347 
1348 #if defined(CONFIG_XRADIO_DEBUG)
1349 		print_hex_dump_bytes("p2p_set_ps_modeinfo: ", DUMP_PREFIX_NONE,
1350 				     (u8 *)modeinfo, sizeof(*modeinfo));
1351 #endif /* CONFIG_XRADIO_DEBUG */
1352 
1353 		if (priv->join_status == XRADIO_JOIN_STATUS_STA ||
1354 		    priv->join_status == XRADIO_JOIN_STATUS_AP) {
1355 			SYS_WARN(wsm_set_p2p_ps_modeinfo(hw_priv, modeinfo, priv->if_id));
1356 		}
1357 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
1358 		/* Temporary solution while firmware don't support NOA change
1359 		 * notification yet */
1360 		xradio_notify_noa(priv, 10);
1361 #endif
1362 	}
1363 #endif /* CONFIG_XRADIO_USE_EXTENSIONS */
1364 
1365 	up(&hw_priv->conf_lock);
1366 }
1367 
xradio_multicast_start_work(struct work_struct * work)1368 void xradio_multicast_start_work(struct work_struct *work)
1369 {
1370 	struct xradio_vif *priv =
1371 	    container_of(work, struct xradio_vif, multicast_start_work);
1372 	long tmo = priv->join_dtim_period * (priv->beacon_int + 20) * HZ / 1024;
1373 
1374 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1375 
1376 	cancel_work_sync(&priv->multicast_stop_work);
1377 	if (!priv->aid0_bit_set) {
1378 		wsm_lock_tx(priv->hw_priv);
1379 		xradio_set_tim_impl(priv, true);
1380 		priv->aid0_bit_set = true;
1381 		mod_timer(&priv->mcast_timeout, jiffies + tmo);
1382 		wsm_unlock_tx(priv->hw_priv);
1383 	}
1384 }
1385 
xradio_multicast_stop_work(struct work_struct * work)1386 void xradio_multicast_stop_work(struct work_struct *work)
1387 {
1388 	struct xradio_vif *priv =
1389 	    container_of(work, struct xradio_vif, multicast_stop_work);
1390 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1391 
1392 	if (priv->aid0_bit_set) {
1393 		del_timer_sync(&priv->mcast_timeout);
1394 		wsm_lock_tx(priv->hw_priv);
1395 		priv->aid0_bit_set = false;
1396 		xradio_set_tim_impl(priv, false);
1397 		wsm_unlock_tx(priv->hw_priv);
1398 	}
1399 }
1400 
xradio_mcast_timeout(struct timer_list * t)1401 void xradio_mcast_timeout(struct timer_list *t)
1402 {
1403 	struct xradio_vif *priv = from_timer(priv, t, mcast_timeout);
1404 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1405 
1406 	ap_printk(XRADIO_DBG_WARN, "Multicast delivery timeout.\n");
1407 	spin_lock_bh(&priv->ps_state_lock);
1408 	priv->tx_multicast = priv->aid0_bit_set && priv->buffered_multicasts;
1409 	if (priv->tx_multicast)
1410 		xradio_proc_wakeup(xrwl_vifpriv_to_hwpriv(priv));
1411 	spin_unlock_bh(&priv->ps_state_lock);
1412 }
1413 
xradio_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)1414 int xradio_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1415 			struct ieee80211_ampdu_params *params)
1416 {
1417 	/* Aggregation is implemented fully in firmware,
1418 	 * including block ack negotiation.
1419 	 * In case of AMPDU aggregation in RX direction
1420 	 * re-ordering of packets takes place on host. mac80211
1421 	 * needs the ADDBA Request to setup reodering.mac80211 also
1422 	 * sends ADDBA Response which is discarded in the driver as
1423 	 * FW generates the ADDBA Response on its own.*/
1424 	int ret;
1425 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1426 
1427 	switch (params->action) {
1428 	case IEEE80211_AMPDU_RX_START:
1429 	case IEEE80211_AMPDU_RX_STOP:
1430 		/* Just return OK to mac80211 */
1431 		ret = 0;
1432 		break;
1433 	default:
1434 		ret = -ENOTSUPP;
1435 	}
1436 	return ret;
1437 }
1438 
1439 /* ******************************************************************** */
1440 /* WSM callback								*/
xradio_suspend_resume(struct xradio_vif * priv,struct wsm_suspend_resume * arg)1441 void xradio_suspend_resume(struct xradio_vif *priv,
1442 			   struct wsm_suspend_resume *arg)
1443 {
1444 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1445 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1446 
1447 #if 0
1448 	ap_printk(XRADIO_DBG_MSG, "[AP] %s: %s\n",
1449 		  arg->stop ? "stop" : "start",
1450 		  arg->multicast ? "broadcast" : "unicast");
1451 #endif
1452 	if (arg->multicast) {
1453 		bool cancel_tmo = false;
1454 		spin_lock_bh(&priv->ps_state_lock);
1455 		if (arg->stop) {
1456 			priv->tx_multicast = false;
1457 		} else {
1458 			/* Firmware sends this indication every DTIM if there
1459 			 * is a STA in powersave connected. There is no reason
1460 			 * to suspend, following wakeup will consume much more
1461 			 * power than it could be saved. */
1462 #ifdef CONFIG_PM
1463 #ifndef CONFIG_XRADIO_SUSPEND_POWER_OFF
1464 			xradio_pm_stay_awake(&hw_priv->pm_state,
1465 					     (priv->join_dtim_period * \
1466 					     (priv->beacon_int + 20) * HZ / 1024));
1467 #endif
1468 #endif
1469 			priv->tx_multicast = priv->aid0_bit_set &&
1470 					     priv->buffered_multicasts;
1471 			if (priv->tx_multicast) {
1472 				cancel_tmo = true;
1473 				xradio_proc_wakeup(hw_priv);
1474 			}
1475 		}
1476 		spin_unlock_bh(&priv->ps_state_lock);
1477 		if (cancel_tmo)
1478 			del_timer_sync(&priv->mcast_timeout);
1479 	} else {
1480 		spin_lock_bh(&priv->ps_state_lock);
1481 		xradio_ps_notify(priv, arg->link_id, arg->stop);
1482 		spin_unlock_bh(&priv->ps_state_lock);
1483 		if (!arg->stop)
1484 			xradio_proc_wakeup(hw_priv);
1485 	}
1486 	return;
1487 }
1488 
1489 /* ******************************************************************** */
1490 /* AP privates								*/
1491 
xradio_upload_beacon(struct xradio_vif * priv)1492 static int xradio_upload_beacon(struct xradio_vif *priv)
1493 {
1494 	int ret = 0;
1495 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1496 	struct wsm_template_frame frame = {
1497 		.frame_type = WSM_FRAME_TYPE_BEACON,
1498 	};
1499 	struct ieee80211_mgmt *mgmt;
1500 	u8 *erp_inf, *ies, *ht_info;
1501 	u32 ies_len;
1502 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1503 
1504 #ifdef SUPPORT_HT40
1505 
1506 	frame.rate = ((RATE_MODEM_LEGACY  << MODEMTYPE_SHIFT) |
1507 				(RATE_BANDWIDTH_20M << BANDWIDTH_SHIFT));
1508 	if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
1509 		frame.rate |= (A_RATES_OFF << RATEINDEX_SHIFT);
1510 
1511 #else
1512 
1513 	if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
1514 		frame.rate = WSM_TRANSMIT_RATE_6;
1515 
1516 #endif
1517 
1518 	frame.skb = ieee80211_beacon_get(priv->hw, priv->vif);
1519 	if (SYS_WARN(!frame.skb))
1520 		return -ENOMEM;
1521 
1522 	mgmt = (void *)frame.skb->data;
1523 	ies = mgmt->u.beacon.variable;
1524 	ies_len = frame.skb->len - (u32) (ies - (u8 *) mgmt);
1525 
1526 	ht_info = (u8 *)cfg80211_find_ie(WLAN_EID_HT_INFORMATION, ies, ies_len);
1527 	if (ht_info) {
1528 		/* Enable RIFS */
1529 		ht_info[3] |= 8;
1530 	}
1531 
1532 	erp_inf = (u8 *)cfg80211_find_ie(WLAN_EID_ERP_INFO, ies, ies_len);
1533 	if (erp_inf) {
1534 		if (erp_inf[ERP_INFO_BYTE_OFFSET]
1535 				& WLAN_ERP_BARKER_PREAMBLE)
1536 			priv->erp_info |= WLAN_ERP_BARKER_PREAMBLE;
1537 		else
1538 			priv->erp_info &= ~WLAN_ERP_BARKER_PREAMBLE;
1539 
1540 		if (erp_inf[ERP_INFO_BYTE_OFFSET]
1541 				& WLAN_ERP_NON_ERP_PRESENT) {
1542 			ap_printk(XRADIO_DBG_NIY, "WLAN_ERP_NON_ERP_PRESENT.\n");
1543 			priv->erp_info |= WLAN_ERP_USE_PROTECTION;
1544 			priv->erp_info |= WLAN_ERP_NON_ERP_PRESENT;
1545 		} else {
1546 			ap_printk(XRADIO_DBG_NIY, "No WLAN_ERP_NON_ERP_PRESENT.\n");
1547 			priv->erp_info &= ~WLAN_ERP_USE_PROTECTION;
1548 			priv->erp_info &= ~WLAN_ERP_NON_ERP_PRESENT;
1549 		}
1550 	}
1551 
1552 #ifdef HIDDEN_SSID
1553 	if (priv->hidden_ssid) {
1554 		u8 *ssid_ie;
1555 		u8 ssid_len;
1556 		/*
1557 		 * Hidden ap set by two ways:
1558 		 * 1. ssid len != 0, and ssid filled with zero.
1559 		 * 2. ssid len = 0, and no ssid in beacon or probe_resp.
1560 		 */
1561 		ap_printk(XRADIO_DBG_NIY, "%s: hidden_ssid set\n", __func__);
1562 		ssid_ie = (u8 *) cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len);
1563 		SYS_WARN(!ssid_ie);
1564 		ssid_len = ssid_ie[1];
1565 		if (ssid_len) {
1566 			ap_printk(XRADIO_DBG_MSG, "hidden_ssid with zero content ssid\n");
1567 			ssid_ie[1] = 0;
1568 			memmove(ssid_ie + 2, ssid_ie + 2 + ssid_len,
1569 				(ies + ies_len - (ssid_ie + 2 + ssid_len)));
1570 			frame.skb->len -= ssid_len;
1571 		} else {
1572 			ap_printk(XRADIO_DBG_NIY,
1573 				  "hidden ssid with ssid len 0, we have nothing to do!");
1574 		}
1575 	}
1576 #endif
1577 
1578 	ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
1579 	if (!ret) {
1580 #ifdef PROBE_RESP_EXTRA_IE
1581 		ret = xradio_upload_proberesp(priv);
1582 #else
1583 		/* TODO: Distille probe resp; remove TIM
1584 		 * and other beacon-specific IEs */
1585 		*(__le16 *)frame.skb->data =
1586 		    __cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
1587 		frame.frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE;
1588 		/* TODO: Ideally probe response template should separately
1589 		   configured by supplicant through openmac. This is a
1590 		   temporary work-around known to fail p2p group info
1591 		   attribute related tests
1592 		 */
1593 		if (0 /* priv->vif->p2p */)
1594 			ret = wsm_set_probe_responder(priv, true);
1595 		else {
1596 			ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
1597 			SYS_WARN(wsm_set_probe_responder(priv, false));
1598 		}
1599 #endif
1600 	}
1601 	dev_kfree_skb(frame.skb);
1602 
1603 	return ret;
1604 }
1605 
1606 #ifdef PROBE_RESP_EXTRA_IE
xradio_upload_proberesp(struct xradio_vif * priv)1607 static int xradio_upload_proberesp(struct xradio_vif *priv)
1608 {
1609 	int ret = 0;
1610 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1611 	struct wsm_template_frame frame = {
1612 		.frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE,
1613 	};
1614 #ifdef HIDDEN_SSID
1615 	u8 *ssid_ie;
1616 #endif
1617 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1618 
1619 #ifdef SUPPORT_HT40
1620 
1621 	frame.rate = ((RATE_MODEM_LEGACY  << MODEMTYPE_SHIFT) |
1622 				(RATE_BANDWIDTH_20M << BANDWIDTH_SHIFT));
1623 	if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
1624 		frame.rate |= (A_RATES_OFF << RATEINDEX_SHIFT);
1625 
1626 #else
1627 
1628 	if (priv->vif->p2p || hw_priv->channel->band == NL80211_BAND_5GHZ)
1629 		frame.rate = WSM_TRANSMIT_RATE_6;
1630 
1631 #endif
1632 
1633 	frame.skb = mac80211_proberesp_get(priv->hw, priv->vif);
1634 	if (frame.skb == NULL) {
1635 		frame.skb = mac80211_proberesp_ext_get(priv->hw, priv->vif);
1636 		if (frame.skb == NULL) {
1637 			ap_printk(XRADIO_DBG_ERROR, "mac80211_proberesp_ext_get frame.skb is null");
1638 			return -ENOMEM;
1639 		}
1640 	}
1641 	if (SYS_WARN(!frame.skb))
1642 		return -ENOMEM;
1643 
1644 #ifdef HIDDEN_SSID
1645 	if (priv->hidden_ssid) {
1646 		int offset;
1647 		u8 ssid_len;
1648 		/* we are assuming beacon from upper layer will always contain
1649 		 * zero filled ssid for hidden ap. The beacon shall never have
1650 		 * ssid len = 0.
1651 		 */
1652 		/* Upper layer will set ssid len = 0 for for hidden ap too.
1653 		 * --13:23 2017/1/9
1654 		 */
1655 
1656 		offset  = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
1657 		ssid_ie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID,
1658 						 frame.skb->data + offset,
1659 						 frame.skb->len - offset);
1660 		if (!ssid_ie) {
1661 			ap_printk(XRADIO_DBG_ERROR,
1662 					  "%s:ssid is not found in probe_resp\n", __func__);
1663 			dev_kfree_skb(frame.skb);
1664 			return -1;
1665 		}
1666 
1667 		if (!priv->ssid_length) {
1668 			ap_printk(XRADIO_DBG_ERROR,
1669 				  "%s:hidden ssid is Not config yet.\n", __func__);
1670 			dev_kfree_skb(frame.skb);
1671 			return -1;
1672 		} else {
1673 			ap_printk(XRADIO_DBG_NIY,
1674 				  "%s: hidden ssid in probe_resp=%s\n",
1675 				  __func__, priv->ssid);
1676 		}
1677 
1678 		ssid_len = ssid_ie[1];
1679 		if (ssid_len) {
1680 			if (ssid_len == priv->ssid_length) {
1681 				memcpy(ssid_ie + 2, priv->ssid, ssid_len);
1682 			} else {
1683 				ap_printk(XRADIO_DBG_ERROR,
1684 					  "%s: hidden ssid with mismatched ssid_len %d\n",
1685 					  __func__, ssid_len);
1686 				dev_kfree_skb(frame.skb);
1687 				return -1;
1688 			}
1689 		} else {
1690 			if (skb_tailroom(frame.skb) >= priv->ssid_length) {
1691 				u8 move_len = (frame.skb->data +
1692 						frame.skb->len) - (ssid_ie + 2);
1693 				skb_put(frame.skb, priv->ssid_length);
1694 				ssid_ie[1] = priv->ssid_length;
1695 				memmove(&ssid_ie[2 + priv->ssid_length],
1696 						&ssid_ie[2], move_len);
1697 				memcpy(&ssid_ie[2], priv->ssid, priv->ssid_length);
1698 			} else {
1699 				ap_printk(XRADIO_DBG_ERROR,
1700 				  "%s: no room in probe_resp for hidden ssid len=%zu\n",
1701 				  __func__, priv->ssid_length);
1702 				dev_kfree_skb(frame.skb);
1703 				return -1;
1704 			}
1705 		}
1706 	}
1707 #endif
1708 	ret = wsm_set_template_frame(hw_priv, &frame,  priv->if_id);
1709 	SYS_WARN(wsm_set_probe_responder(priv, false));
1710 
1711 	dev_kfree_skb(frame.skb);
1712 
1713 	return ret;
1714 }
1715 #endif
1716 
xradio_upload_pspoll(struct xradio_vif * priv)1717 static int xradio_upload_pspoll(struct xradio_vif *priv)
1718 {
1719 	int ret = 0;
1720 	struct wsm_template_frame frame = {
1721 		.frame_type = WSM_FRAME_TYPE_PS_POLL,
1722 		.rate = 0xFF,
1723 	};
1724 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1725 
1726 	frame.skb = mac80211_pspoll_get(priv->hw, priv->vif);
1727 	if (SYS_WARN(!frame.skb))
1728 		return -ENOMEM;
1729 	ret = wsm_set_template_frame(xrwl_vifpriv_to_hwpriv(priv),
1730 				     &frame, priv->if_id);
1731 	dev_kfree_skb(frame.skb);
1732 	return ret;
1733 }
1734 
xradio_upload_null(struct xradio_vif * priv)1735 static int xradio_upload_null(struct xradio_vif *priv)
1736 {
1737 	int ret = 0;
1738 	struct wsm_template_frame frame = {
1739 		.frame_type = WSM_FRAME_TYPE_NULL,
1740 		.rate = 0xFF,
1741 	};
1742 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1743 
1744 	frame.skb = mac80211_nullfunc_get(priv->hw, priv->vif, false);
1745 
1746 	if (SYS_WARN(!frame.skb))
1747 		return -ENOMEM;
1748 
1749 	ret = wsm_set_template_frame(xrwl_vifpriv_to_hwpriv(priv),
1750 				     &frame, priv->if_id);
1751 	dev_kfree_skb(frame.skb);
1752 	return ret;
1753 }
1754 
xradio_upload_qosnull(struct xradio_vif * priv)1755 static int xradio_upload_qosnull(struct xradio_vif *priv)
1756 {
1757 	int ret = 0;
1758 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1759 	struct wsm_template_frame frame = {
1760 		.frame_type = WSM_FRAME_TYPE_QOS_NULL,
1761 		.rate = 0xFF,
1762 	};
1763 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1764 
1765 	frame.skb = ieee80211_qosnullfunc_get(priv->hw, priv->vif);
1766 	if (SYS_WARN(!frame.skb))
1767 		return -ENOMEM;
1768 
1769 	ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
1770 	dev_kfree_skb(frame.skb);
1771 	return ret;
1772 }
1773 
1774 /* This API is nolonegr present in WSC */
1775 #if 0
1776 static int xradio_enable_beaconing(struct xradio_vif *priv, bool enable)
1777 {
1778 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1779 	struct wsm_beacon_transmit transmit = {
1780 		.enableBeaconing = enable,
1781 	};
1782 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1783 
1784 	return wsm_beacon_transmit(hw_priv, &transmit, priv->if_id);
1785 }
1786 #endif
1787 
xradio_start_ap(struct xradio_vif * priv)1788 static int xradio_start_ap(struct xradio_vif *priv)
1789 {
1790 	int ret;
1791 #ifndef HIDDEN_SSID
1792 	const u8 *ssidie;
1793 	struct sk_buff *skb;
1794 	int offset;
1795 #endif
1796 	struct ieee80211_bss_conf *conf = &priv->vif->bss_conf;
1797 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
1798 
1799 	enum nl80211_channel_type chan_type = cfg80211_get_chandef_type(&conf->chandef);
1800 #ifdef SUPPORT_HT40
1801 
1802 	struct ieee80211_supported_band *sband;
1803 	struct phy_mode_cfg PhyModeCfg;
1804 
1805 	struct wsm_start start = {
1806 		.mode = priv->vif->p2p ? WSM_START_MODE_P2P_GO :
1807 					WSM_START_MODE_AP,
1808 		/* TODO:COMBO:Change once mac80211 support is available */
1809 		.channelNumber = hw_priv->channel->hw_value,
1810 		.beaconInterval = conf->beacon_int,
1811 		.DTIMPeriod = conf->dtim_period,
1812 		.probeDelay = 100,
1813 		.basicRateSet =
1814 			xradio_rate_mask_to_wsm(hw_priv, conf->basic_rates),
1815 #ifdef P2P_MULTIVIF
1816 		.CTWindow = priv->vif->p2p ? 0xFFFFFFFF : 0,
1817 #endif
1818 	};
1819 
1820 #else
1821 
1822 	struct wsm_start start = {
1823 		.mode = priv->vif->p2p ? WSM_START_MODE_P2P_GO : WSM_START_MODE_AP,
1824 		/* TODO:COMBO:Change once mac80211 support is available */
1825 		.band = (hw_priv->channel->band == NL80211_BAND_5GHZ) ?
1826 				     WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G,
1827 		.channelNumber = hw_priv->channel->hw_value,
1828 		.beaconInterval = conf->beacon_int,
1829 		.DTIMPeriod = conf->dtim_period,
1830 		.preambleType = conf->use_short_preamble ?
1831 				WSM_JOIN_PREAMBLE_SHORT : WSM_JOIN_PREAMBLE_LONG,
1832 		.probeDelay = 100,
1833 		.basicRateSet = xradio_rate_mask_to_wsm(hw_priv, conf->basic_rates),
1834 #ifdef P2P_MULTIVIF
1835 		.CTWindow = priv->vif->p2p ? 0xFFFFFFFF : 0,
1836 #endif
1837 	};
1838 
1839 #endif
1840 
1841 	struct wsm_operational_mode mode = {
1842 		.power_mode = wsm_power_mode_quiescent,
1843 		.disableMoreFlagUsage = true,
1844 	};
1845 
1846 #ifdef TES_P2P_000B_EXTEND_INACTIVITY_CNT
1847 	/*
1848 	 * TES_P2P_000B WorkAround:
1849 	 * when inactivity count of a peer device is zero,
1850 	 * which will reset while receiving a peer device frame,
1851 	 * firmware will disconnect with it.
1852 	 * due to some reason, such as scan/phy error, we miss these frame.
1853 	 * then we can't keep connection with peer device.
1854 	 * we set the min_inactivity value to large as WorkAround.
1855 	 */
1856 	struct wsm_inactivity inactivity = {
1857 		.min_inactivity = 20,
1858 		.max_inactivity = 10,
1859 	};
1860 #else
1861 	struct wsm_inactivity inactivity = {
1862 		.min_inactivity = 9,
1863 		.max_inactivity = 1,
1864 	};
1865 #endif
1866 
1867 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
1868 
1869 #ifdef SUPPORT_HT40
1870 
1871 	sband = priv->hw->wiphy->bands[hw_priv->channel->band];
1872 
1873 	PhyModeCfg.BandCfg = hw_priv->channel->band;
1874 	if (PhyModeCfg.BandCfg == NL80211_BAND_5GHZ)
1875 		PhyModeCfg.ModemFlags = (MODEM_F_A_OFDM |
1876 					MODEM_F_N_OFDM);
1877 	else
1878 		PhyModeCfg.ModemFlags = (MODEM_F_B_DSSS |
1879 					MODEM_F_A_OFDM |
1880 					MODEM_F_N_OFDM);
1881 
1882 	if (chan_type == NL80211_CHAN_HT40MINUS) {
1883 		PhyModeCfg.ChWidthCfg = CHAN_WIDTH_40MHz;
1884 		PhyModeCfg.PriChCfg   = PRIMARY_CH_1ST;
1885 	} else if (chan_type == NL80211_CHAN_HT40PLUS) {
1886 		PhyModeCfg.ChWidthCfg = CHAN_WIDTH_40MHz;
1887 		PhyModeCfg.PriChCfg   = PRIMARY_CH_2ND;
1888 	} else {
1889 		PhyModeCfg.ChWidthCfg = CHAN_WIDTH_20MHz;
1890 		PhyModeCfg.PriChCfg   = PRIMARY_CH_1ST;
1891 	}
1892 
1893 	if (chan_type == NL80211_CHAN_NO_HT) {
1894 		PhyModeCfg.ModemFlags &= ~(MODEM_F_N_OFDM);
1895 		PhyModeCfg.SGI_Enable = false;
1896 		PhyModeCfg.GF_Enable = false;
1897 	} else {
1898 		PhyModeCfg.GF_Enable  =
1899 			(sband->ht_cap.cap&IEEE80211_HT_CAP_GRN_FLD) ?
1900 								true : false;
1901 		PhyModeCfg.SGI_Enable =
1902 			(sband->ht_cap.cap&
1903 			(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) ?
1904 								true : false;
1905 	}
1906 
1907 	PhyModeCfg.STBC_Enable = false;
1908 	PhyModeCfg.PreambleCfg = conf->use_short_preamble ?
1909 		WSM_JOIN_PREAMBLE_SHORT : WSM_JOIN_PREAMBLE_LONG;
1910 
1911 	start.PhyModeCfg = PhyModeCfg;
1912 
1913 #endif
1914 
1915 	if (priv->if_id)
1916 		start.mode |= WSM_FLAG_MAC_INSTANCE_1;
1917 	else
1918 		start.mode &= ~WSM_FLAG_MAC_INSTANCE_1;
1919 
1920 	hw_priv->connected_sta_cnt = 0;
1921 
1922 #ifndef HIDDEN_SSID
1923 	/* Get SSID */
1924 	skb = ieee80211_beacon_get(priv->hw, priv->vif);
1925 	if (SYS_WARN(!skb)) {
1926 		ap_printk(XRADIO_DBG_ERROR, "%s, ieee80211_beacon_get failed\n",
1927 			  __func__);
1928 		return -ENOMEM;
1929 	}
1930 
1931 	offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
1932 	ssidie = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset,
1933 				  skb->len - offset);
1934 
1935 	memset(priv->ssid, 0, sizeof(priv->ssid));
1936 	if (ssidie) {
1937 		priv->ssid_length = ssidie[1];
1938 		if (SYS_WARN(priv->ssid_length > sizeof(priv->ssid)))
1939 			priv->ssid_length = sizeof(priv->ssid);
1940 		memcpy(priv->ssid, &ssidie[2], priv->ssid_length);
1941 	} else {
1942 		priv->ssid_length = 0;
1943 	}
1944 	dev_kfree_skb(skb);
1945 #endif
1946 
1947 	priv->beacon_int = conf->beacon_int;
1948 	priv->join_dtim_period = conf->dtim_period;
1949 	memset(&priv->last_tim[0], 0, sizeof(priv->last_tim));
1950 
1951 	start.ssidLength = priv->ssid_length;
1952 	memcpy(&start.ssid[0], priv->ssid, start.ssidLength);
1953 
1954 	memset(&priv->link_id_db, 0, sizeof(priv->link_id_db));
1955 
1956 #ifdef SUPPORT_HT40
1957 
1958 	ap_printk(XRADIO_DBG_NIY, "[AP] ch: %d(%d), bcn: %d(%d), "\
1959 				"bss_rate: 0x%.8X, ssid: %.*s.\n",
1960 				start.channelNumber, start.PhyModeCfg.BandCfg,
1961 				start.beaconInterval, start.DTIMPeriod,
1962 				start.basicRateSet, start.ssidLength,
1963 				start.ssid);
1964 	ret = SYS_WARN(wsm_start(hw_priv, &start, priv->if_id));
1965 
1966 	ap_printk(XRADIO_DBG_WARN, "[HT40][%s][PhyModeCfg:0x%04x]\n",
1967 				__func__, *(u16 *)&start.PhyModeCfg);
1968 
1969 #else
1970 
1971 	ap_printk(XRADIO_DBG_NIY, "[AP] ch: %d(%d), bcn: %d(%d), " \
1972 		  "bss_rate: 0x%.8X, ssid: %.*s.\n",
1973 		  start.channelNumber,  start.band,
1974 		  start.beaconInterval, start.DTIMPeriod,
1975 		  start.basicRateSet, start.ssidLength, start.ssid);
1976 	ret = SYS_WARN(wsm_start(hw_priv, &start, priv->if_id));
1977 
1978 #endif
1979 	if (!ret && priv->vif->p2p) {
1980 		ap_printk(XRADIO_DBG_NIY,
1981 			  "[AP] Setting p2p powersave configuration.\n");
1982 		SYS_WARN(wsm_set_p2p_ps_modeinfo(hw_priv,
1983 			&priv->p2p_ps_modeinfo, priv->if_id));
1984 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
1985 		xradio_notify_noa(priv, XRADIO_NOA_NOTIFICATION_DELAY);
1986 #endif
1987 	}
1988 
1989 	/*Set Inactivity time */
1990 	if (!(strstr(&start.ssid[0], "6.1.12"))) {
1991 		wsm_set_inactivity(hw_priv, &inactivity, priv->if_id);
1992 	}
1993 	if (!ret) {
1994 #ifndef AP_AGGREGATE_FW_FIX
1995 		SYS_WARN(wsm_set_block_ack_policy(hw_priv,
1996 			 XRADIO_TX_BLOCK_ACK_DISABLED_FOR_ALL_TID,
1997 			 XRADIO_RX_BLOCK_ACK_DISABLED_FOR_ALL_TID, priv->if_id));
1998 #else
1999 		if ((priv->if_id == 1) && !hw_priv->is_go_thru_go_neg)
2000 			SYS_WARN(wsm_set_block_ack_policy(hw_priv,
2001 				 XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
2002 				 XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id));
2003 		else
2004 			SYS_WARN(wsm_set_block_ack_policy(hw_priv,
2005 				 XRADIO_TX_BLOCK_ACK_ENABLED_FOR_ALL_TID,
2006 				 XRADIO_RX_BLOCK_ACK_ENABLED_FOR_ALL_TID, priv->if_id));
2007 #endif
2008 		priv->join_status = XRADIO_JOIN_STATUS_AP;
2009 		/* xradio_update_filtering(priv); */
2010 	}
2011 	SYS_WARN(wsm_set_operational_mode(hw_priv, &mode, priv->if_id));
2012 	hw_priv->vif0_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
2013 	hw_priv->vif1_throttle = XRWL_HOST_VIF0_11N_THROTTLE;
2014 	ap_printk(XRADIO_DBG_WARN, "vif%d, AP/GO mode THROTTLE=%d\n",
2015 		  priv->if_id, priv->if_id == 0 ?
2016 		  hw_priv->vif0_throttle : hw_priv->vif1_throttle);
2017 	return ret;
2018 }
2019 
xradio_update_beaconing(struct xradio_vif * priv)2020 static int xradio_update_beaconing(struct xradio_vif *priv)
2021 {
2022 	struct ieee80211_bss_conf *conf = &priv->vif->bss_conf;
2023 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
2024 	struct wsm_reset reset = {
2025 		.link_id = 0,
2026 		.reset_statistics = true,
2027 	};
2028 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
2029 
2030 	if (priv->mode == NL80211_IFTYPE_AP) {
2031 		/* TODO: check if changed channel, band */
2032 		if (priv->join_status != XRADIO_JOIN_STATUS_AP ||
2033 		    priv->beacon_int != conf->beacon_int) {
2034 			ap_printk(XRADIO_DBG_WARN, "ap restarting!\n");
2035 			wsm_lock_tx(hw_priv);
2036 			if (priv->join_status != XRADIO_JOIN_STATUS_PASSIVE)
2037 				SYS_WARN(wsm_reset(hw_priv, &reset, priv->if_id));
2038 			priv->join_status = XRADIO_JOIN_STATUS_PASSIVE;
2039 			SYS_WARN(xradio_start_ap(priv));
2040 			wsm_unlock_tx(hw_priv);
2041 		} else
2042 			ap_printk(XRADIO_DBG_NIY, "ap started join_status: %d\n",
2043 				  priv->join_status);
2044 	}
2045 	return 0;
2046 }
2047 
xradio_find_link_id(struct xradio_vif * priv,const u8 * mac)2048 int xradio_find_link_id(struct xradio_vif *priv, const u8 *mac)
2049 {
2050 	int i, ret = 0;
2051 	spin_lock_bh(&priv->ps_state_lock);
2052 	for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
2053 		if (!memcmp(mac, priv->link_id_db[i].mac, ETH_ALEN) &&
2054 		    priv->link_id_db[i].status) {
2055 			priv->link_id_db[i].timestamp = jiffies;
2056 			ret = i + 1;
2057 			break;
2058 		}
2059 	}
2060 	spin_unlock_bh(&priv->ps_state_lock);
2061 	return ret;
2062 }
2063 
xradio_alloc_link_id(struct xradio_vif * priv,const u8 * mac)2064 int xradio_alloc_link_id(struct xradio_vif *priv, const u8 *mac)
2065 {
2066 	int i, ret = 0;
2067 	unsigned long max_inactivity = 0;
2068 	unsigned long now = jiffies;
2069 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
2070 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
2071 
2072 	spin_lock_bh(&priv->ps_state_lock);
2073 	for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
2074 		if (!priv->link_id_db[i].status) {
2075 			ret = i + 1;
2076 			break;
2077 		} else if (priv->link_id_db[i].status != XRADIO_LINK_HARD &&
2078 			   !hw_priv->tx_queue_stats.link_map_cache[priv->if_id][i + 1]) {
2079 			unsigned long inactivity = now - priv->link_id_db[i].timestamp;
2080 			if (inactivity < max_inactivity)
2081 				continue;
2082 			max_inactivity = inactivity;
2083 			ret = i + 1;
2084 		}
2085 	}
2086 	if (ret) {
2087 		struct xradio_link_entry *entry = &priv->link_id_db[ret - 1];
2088 		ap_printk(XRADIO_DBG_NIY, "STA added, link_id: %d\n", ret);
2089 		entry->status = XRADIO_LINK_RESERVE;
2090 		memcpy(&entry->mac, mac, ETH_ALEN);
2091 		memset(&entry->buffered, 0, XRADIO_MAX_TID);
2092 		skb_queue_head_init(&entry->rx_queue);
2093 		wsm_lock_tx_async(hw_priv);
2094 		if (queue_work(hw_priv->workqueue, &priv->link_id_work) <= 0)
2095 			wsm_unlock_tx(hw_priv);
2096 	} else {
2097 		ap_printk(XRADIO_DBG_WARN, "Early: no more link IDs available.\n");
2098 	}
2099 
2100 	spin_unlock_bh(&priv->ps_state_lock);
2101 	return ret;
2102 }
2103 
xradio_link_id_work(struct work_struct * work)2104 void xradio_link_id_work(struct work_struct *work)
2105 {
2106 	struct xradio_vif *priv =
2107 	    container_of(work, struct xradio_vif, link_id_work);
2108 	struct xradio_common *hw_priv = priv->hw_priv;
2109 
2110 	wsm_flush_tx(hw_priv);
2111 	xradio_link_id_gc_work(&priv->link_id_gc_work.work);
2112 	wsm_unlock_tx(hw_priv);
2113 }
2114 
xradio_link_id_gc_work(struct work_struct * work)2115 void xradio_link_id_gc_work(struct work_struct *work)
2116 {
2117 	struct xradio_vif *priv =
2118 	    container_of(work, struct xradio_vif, link_id_gc_work.work);
2119 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
2120 	struct wsm_map_link map_link = {
2121 		.link_id = 0,
2122 	};
2123 	unsigned long now = jiffies;
2124 	unsigned long next_gc = -1;
2125 	long ttl;
2126 	bool need_reset;
2127 	u32 mask;
2128 	int i;
2129 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
2130 
2131 	if (priv->join_status != XRADIO_JOIN_STATUS_AP)
2132 		return;
2133 
2134 	wsm_lock_tx(hw_priv);
2135 	spin_lock_bh(&priv->ps_state_lock);
2136 	for (i = 0; i < MAX_STA_IN_AP_MODE; ++i) {
2137 		need_reset = false;
2138 		mask = BIT(i + 1);
2139 		if (priv->link_id_db[i].status == XRADIO_LINK_RESERVE ||
2140 		    (priv->link_id_db[i].status == XRADIO_LINK_HARD &&
2141 		     !(priv->link_id_map & mask))) {
2142 			if (priv->link_id_map & mask) {
2143 				priv->sta_asleep_mask &= ~mask;
2144 				priv->pspoll_mask &= ~mask;
2145 				need_reset = true;
2146 			}
2147 			priv->link_id_map |= mask;
2148 			if (priv->link_id_db[i].status != XRADIO_LINK_HARD)
2149 				priv->link_id_db[i].status = XRADIO_LINK_SOFT;
2150 			memcpy(map_link.mac_addr, priv->link_id_db[i].mac, ETH_ALEN);
2151 			spin_unlock_bh(&priv->ps_state_lock);
2152 			if (need_reset) {
2153 				SYS_WARN(xrwl_unmap_link(priv, i + 1));
2154 			}
2155 			map_link.link_id = i + 1;
2156 			SYS_WARN(wsm_map_link(hw_priv, &map_link, priv->if_id));
2157 			next_gc = min(next_gc, XRADIO_LINK_ID_GC_TIMEOUT);
2158 			spin_lock_bh(&priv->ps_state_lock);
2159 		} else if (priv->link_id_db[i].status == XRADIO_LINK_SOFT) {
2160 			ttl = priv->link_id_db[i].timestamp - now +
2161 			      XRADIO_LINK_ID_GC_TIMEOUT;
2162 			if (ttl <= 0) {
2163 				need_reset = true;
2164 				priv->link_id_db[i].status = XRADIO_LINK_OFF;
2165 				priv->link_id_map &= ~mask;
2166 				priv->sta_asleep_mask &= ~mask;
2167 				priv->pspoll_mask &= ~mask;
2168 				memset(map_link.mac_addr, 0, ETH_ALEN);
2169 				spin_unlock_bh(&priv->ps_state_lock);
2170 				SYS_WARN(xrwl_unmap_link(priv, i + 1));
2171 				spin_lock_bh(&priv->ps_state_lock);
2172 			} else {
2173 				next_gc = min_t(unsigned long, next_gc, ttl);
2174 			}
2175 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
2176 		} else if (priv->link_id_db[i].status == XRADIO_LINK_RESET ||
2177 			   priv->link_id_db[i].status == XRADIO_LINK_RESET_REMAP) {
2178 			int status = priv->link_id_db[i].status;
2179 			priv->link_id_db[i].status = XRADIO_LINK_OFF;
2180 			priv->link_id_db[i].timestamp = now;
2181 			spin_unlock_bh(&priv->ps_state_lock);
2182 			SYS_WARN(xrwl_unmap_link(priv, i + 1));
2183 			if (status == XRADIO_LINK_RESET_REMAP) {
2184 				memcpy(map_link.mac_addr, priv->link_id_db[i].mac, ETH_ALEN);
2185 				map_link.link_id = i + 1;
2186 				SYS_WARN(wsm_map_link(hw_priv, &map_link, priv->if_id));
2187 				next_gc = min(next_gc, XRADIO_LINK_ID_GC_TIMEOUT);
2188 				priv->link_id_db[i].status = priv->link_id_db[i].prev_status;
2189 			}
2190 			spin_lock_bh(&priv->ps_state_lock);
2191 #endif
2192 		}
2193 		if (need_reset) {
2194 			skb_queue_purge(&priv->link_id_db[i].rx_queue);
2195 			ap_printk(XRADIO_DBG_NIY, "STA removed, link_id: %d\n", i + 1);
2196 		}
2197 	}
2198 	spin_unlock_bh(&priv->ps_state_lock);
2199 	if (next_gc != -1)
2200 		queue_delayed_work(hw_priv->workqueue,
2201 				   &priv->link_id_gc_work, next_gc);
2202 	wsm_unlock_tx(hw_priv);
2203 }
2204 
2205 #if defined(CONFIG_XRADIO_USE_EXTENSIONS)
xradio_notify_noa(struct xradio_vif * priv,int delay)2206 void xradio_notify_noa(struct xradio_vif *priv, int delay)
2207 {
2208 #if 0
2209 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
2210 	struct cfg80211_p2p_ps p2p_ps = { 0 };
2211 	struct wsm_p2p_ps_modeinfo *modeinfo;
2212 	modeinfo = &priv->p2p_ps_modeinfo;
2213 
2214 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
2215 
2216 	if (priv->join_status != XRADIO_JOIN_STATUS_AP)
2217 		return;
2218 
2219 	if (delay)
2220 		msleep(delay);
2221 
2222 	if (!SYS_WARN(wsm_get_p2p_ps_modeinfo(hw_priv, modeinfo))) {
2223 #if defined(CONFIG_XRADIO_DEBUG)
2224 		print_hex_dump_bytes("[AP] p2p_get_ps_modeinfo: ", DUMP_PREFIX_NONE,
2225 				    (u8 *)modeinfo, sizeof(*modeinfo));
2226 #endif /* CONFIG_XRADIO_DEBUG */
2227 		p2p_ps.opp_ps = !!(modeinfo->oppPsCTWindow & BIT(7));
2228 		p2p_ps.ctwindow = modeinfo->oppPsCTWindow & (~BIT(7));
2229 		p2p_ps.count = modeinfo->count;
2230 		p2p_ps.start = __le32_to_cpu(modeinfo->startTime);
2231 		p2p_ps.duration = __le32_to_cpu(modeinfo->duration);
2232 		p2p_ps.interval = __le32_to_cpu(modeinfo->interval);
2233 		p2p_ps.index = modeinfo->reserved;
2234 
2235 		/* ieee80211_p2p_noa_notify(priv->vif, &p2p_ps, GFP_KERNEL); */
2236 	}
2237 #endif
2238 }
2239 #endif
2240 
xrwl_unmap_link(struct xradio_vif * priv,int link_id)2241 int xrwl_unmap_link(struct xradio_vif *priv, int link_id)
2242 {
2243 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
2244 	int ret = 0;
2245 	struct wsm_operational_mode mode = {
2246 		.power_mode = wsm_power_mode_quiescent,
2247 		.disableMoreFlagUsage = true,
2248 	};
2249 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
2250 
2251 	if (is_hardware_xradio(hw_priv)) {
2252 		struct wsm_map_link maplink = {
2253 			.link_id = link_id,
2254 			.unmap = true,
2255 		};
2256 		if (link_id)
2257 			memcpy(&maplink.mac_addr[0],
2258 			       priv->link_id_db[link_id - 1].mac, ETH_ALEN);
2259 		return wsm_map_link(hw_priv, &maplink, priv->if_id);
2260 	} else {
2261 		struct wsm_reset reset = {
2262 			.link_id = link_id,
2263 			.reset_statistics = true,
2264 		};
2265 		ret = wsm_reset(hw_priv, &reset, priv->if_id);
2266 		SYS_WARN(wsm_set_operational_mode(hw_priv, &mode, priv->if_id));
2267 		return ret;
2268 	}
2269 }
2270 
2271 #ifdef AP_HT_CAP_UPDATE
xradio_ht_info_update_work(struct work_struct * work)2272 void xradio_ht_info_update_work(struct work_struct *work)
2273 {
2274 	struct sk_buff *skb;
2275 	struct ieee80211_mgmt *mgmt;
2276 	u8 *ht_info, *ies;
2277 	u32 ies_len;
2278 	struct xradio_vif *priv =
2279 	    container_of(work, struct xradio_vif, ht_info_update_work);
2280 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
2281 	struct wsm_update_ie update_ie = {
2282 		.what = WSM_UPDATE_IE_BEACON,
2283 		.count = 1,
2284 	};
2285 	ap_printk(XRADIO_DBG_TRC, "%s\n", __func__);
2286 
2287 	skb = ieee80211_beacon_get(priv->hw, priv->vif);
2288 	if (SYS_WARN(!skb))
2289 		return;
2290 
2291 	mgmt = (void *)skb->data;
2292 	ies = mgmt->u.beacon.variable;
2293 	ies_len = skb->len - (u32)(ies - (u8 *)mgmt);
2294 	ht_info = (u8 *)cfg80211_find_ie(WLAN_EID_HT_INFORMATION, ies, ies_len);
2295 	if (ht_info && priv->ht_info == HT_INFO_MASK) {
2296 		ht_info[HT_INFO_OFFSET] |= 0x11;
2297 		update_ie.ies = ht_info;
2298 		update_ie.length = HT_INFO_IE_LEN + 2;
2299 		SYS_WARN(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
2300 	}
2301 	dev_kfree_skb(skb);
2302 }
2303 #endif
2304