• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _RTW_HWMP_C_
16 
17 #ifdef CONFIG_RTW_MESH
18 #include <drv_types.h>
19 #include <hal_data.h>
20 
21 #define RTW_TEST_FRAME_LEN	8192
22 #define RTW_MAX_METRIC	0xffffffff
23 #define RTW_ARITH_SHIFT	8
24 #define RTW_LINK_FAIL_THRESH 95
25 #define RTW_MAX_PREQ_QUEUE_LEN	64
26 #define RTW_ATLM_REQ_CYCLE 1000
27 
28 #define rtw_ilog2(n)			\
29 (					\
30 	(n) < 2 ? 0 :			\
31 	(n) & (1ULL << 63) ? 63 :	\
32 	(n) & (1ULL << 62) ? 62 :	\
33 	(n) & (1ULL << 61) ? 61 :	\
34 	(n) & (1ULL << 60) ? 60 :	\
35 	(n) & (1ULL << 59) ? 59 :	\
36 	(n) & (1ULL << 58) ? 58 :	\
37 	(n) & (1ULL << 57) ? 57 :	\
38 	(n) & (1ULL << 56) ? 56 :	\
39 	(n) & (1ULL << 55) ? 55 :	\
40 	(n) & (1ULL << 54) ? 54 :	\
41 	(n) & (1ULL << 53) ? 53 :	\
42 	(n) & (1ULL << 52) ? 52 :	\
43 	(n) & (1ULL << 51) ? 51 :	\
44 	(n) & (1ULL << 50) ? 50 :	\
45 	(n) & (1ULL << 49) ? 49 :	\
46 	(n) & (1ULL << 48) ? 48 :	\
47 	(n) & (1ULL << 47) ? 47 :	\
48 	(n) & (1ULL << 46) ? 46 :	\
49 	(n) & (1ULL << 45) ? 45 :	\
50 	(n) & (1ULL << 44) ? 44 :	\
51 	(n) & (1ULL << 43) ? 43 :	\
52 	(n) & (1ULL << 42) ? 42 :	\
53 	(n) & (1ULL << 41) ? 41 :	\
54 	(n) & (1ULL << 40) ? 40 :	\
55 	(n) & (1ULL << 39) ? 39 :	\
56 	(n) & (1ULL << 38) ? 38 :	\
57 	(n) & (1ULL << 37) ? 37 :	\
58 	(n) & (1ULL << 36) ? 36 :	\
59 	(n) & (1ULL << 35) ? 35 :	\
60 	(n) & (1ULL << 34) ? 34 :	\
61 	(n) & (1ULL << 33) ? 33 :	\
62 	(n) & (1ULL << 32) ? 32 :	\
63 	(n) & (1ULL << 31) ? 31 :	\
64 	(n) & (1ULL << 30) ? 30 :	\
65 	(n) & (1ULL << 29) ? 29 :	\
66 	(n) & (1ULL << 28) ? 28 :	\
67 	(n) & (1ULL << 27) ? 27 :	\
68 	(n) & (1ULL << 26) ? 26 :	\
69 	(n) & (1ULL << 25) ? 25 :	\
70 	(n) & (1ULL << 24) ? 24 :	\
71 	(n) & (1ULL << 23) ? 23 :	\
72 	(n) & (1ULL << 22) ? 22 :	\
73 	(n) & (1ULL << 21) ? 21 :	\
74 	(n) & (1ULL << 20) ? 20 :	\
75 	(n) & (1ULL << 19) ? 19 :	\
76 	(n) & (1ULL << 18) ? 18 :	\
77 	(n) & (1ULL << 17) ? 17 :	\
78 	(n) & (1ULL << 16) ? 16 :	\
79 	(n) & (1ULL << 15) ? 15 :	\
80 	(n) & (1ULL << 14) ? 14 :	\
81 	(n) & (1ULL << 13) ? 13 :	\
82 	(n) & (1ULL << 12) ? 12 :	\
83 	(n) & (1ULL << 11) ? 11 :	\
84 	(n) & (1ULL << 10) ? 10 :	\
85 	(n) & (1ULL <<  9) ?  9 :	\
86 	(n) & (1ULL <<  8) ?  8 :	\
87 	(n) & (1ULL <<  7) ?  7 :	\
88 	(n) & (1ULL <<  6) ?  6 :	\
89 	(n) & (1ULL <<  5) ?  5 :	\
90 	(n) & (1ULL <<  4) ?  4 :	\
91 	(n) & (1ULL <<  3) ?  3 :	\
92 	(n) & (1ULL <<  2) ?  2 :	\
93 	1				\
94 )
95 
96 enum rtw_mpath_frame_type {
97 	RTW_MPATH_PREQ = 0,
98 	RTW_MPATH_PREP,
99 	RTW_MPATH_PERR,
100 	RTW_MPATH_RANN
101 };
102 
rtw_u32_field_get(const u8 * preq_elem,int shift,BOOLEAN ae)103 static inline u32 rtw_u32_field_get(const u8 *preq_elem, int shift, BOOLEAN ae)
104 {
105 	if (ae)
106 		shift += 6;
107 	return LE_BITS_TO_4BYTE(preq_elem + shift, 0, 32);
108 }
109 
rtw_u16_field_get(const u8 * preq_elem,int shift,BOOLEAN ae)110 static inline u16 rtw_u16_field_get(const u8 *preq_elem, int shift, BOOLEAN ae)
111 {
112 	if (ae)
113 		shift += 6;
114 	return LE_BITS_TO_2BYTE(preq_elem + shift, 0, 16);
115 }
116 
117 /* HWMP IE processing macros */
118 #define RTW_AE_F			(1<<6)
119 #define RTW_AE_F_SET(x)			(*x & RTW_AE_F)
120 #define RTW_PREQ_IE_FLAGS(x)		(*(x))
121 #define RTW_PREQ_IE_HOPCOUNT(x)		(*(x + 1))
122 #define RTW_PREQ_IE_TTL(x)		(*(x + 2))
123 #define RTW_PREQ_IE_PREQ_ID(x)		rtw_u32_field_get(x, 3, 0)
124 #define RTW_PREQ_IE_ORIG_ADDR(x)	(x + 7)
125 #define RTW_PREQ_IE_ORIG_SN(x)		rtw_u32_field_get(x, 13, 0)
126 #define RTW_PREQ_IE_LIFETIME(x)		rtw_u32_field_get(x, 17, RTW_AE_F_SET(x))
127 #define RTW_PREQ_IE_METRIC(x) 		rtw_u32_field_get(x, 21, RTW_AE_F_SET(x))
128 #define RTW_PREQ_IE_TARGET_F(x)		(*(RTW_AE_F_SET(x) ? x + 32 : x + 26))
129 #define RTW_PREQ_IE_TARGET_ADDR(x) 	(RTW_AE_F_SET(x) ? x + 33 : x + 27)
130 #define RTW_PREQ_IE_TARGET_SN(x) 	rtw_u32_field_get(x, 33, RTW_AE_F_SET(x))
131 
132 #define RTW_PREP_IE_FLAGS(x)		RTW_PREQ_IE_FLAGS(x)
133 #define RTW_PREP_IE_HOPCOUNT(x)		RTW_PREQ_IE_HOPCOUNT(x)
134 #define RTW_PREP_IE_TTL(x)		RTW_PREQ_IE_TTL(x)
135 #define RTW_PREP_IE_ORIG_ADDR(x)	(RTW_AE_F_SET(x) ? x + 27 : x + 21)
136 #define RTW_PREP_IE_ORIG_SN(x)		rtw_u32_field_get(x, 27, RTW_AE_F_SET(x))
137 #define RTW_PREP_IE_LIFETIME(x)		rtw_u32_field_get(x, 13, RTW_AE_F_SET(x))
138 #define RTW_PREP_IE_METRIC(x)		rtw_u32_field_get(x, 17, RTW_AE_F_SET(x))
139 #define RTW_PREP_IE_TARGET_ADDR(x)	(x + 3)
140 #define RTW_PREP_IE_TARGET_SN(x)	rtw_u32_field_get(x, 9, 0)
141 
142 #define RTW_PERR_IE_TTL(x)		(*(x))
143 #define RTW_PERR_IE_TARGET_FLAGS(x)	(*(x + 2))
144 #define RTW_PERR_IE_TARGET_ADDR(x)	(x + 3)
145 #define RTW_PERR_IE_TARGET_SN(x)	rtw_u32_field_get(x, 9, 0)
146 #define RTW_PERR_IE_TARGET_RCODE(x)	rtw_u16_field_get(x, 13, 0)
147 
148 #define RTW_TU_TO_SYSTIME(x)	(rtw_us_to_systime((x) * 1024))
149 #define RTW_TU_TO_EXP_TIME(x)	(rtw_get_current_time() + RTW_TU_TO_SYSTIME(x))
150 #define RTW_MSEC_TO_TU(x) (x*1000/1024)
151 #define RTW_SN_GT(x, y) ((s32)(y - x) < 0)
152 #define RTW_SN_LT(x, y) ((s32)(x - y) < 0)
153 #define RTW_MAX_SANE_SN_DELTA 32
154 
RTW_SN_DELTA(u32 x,u32 y)155 static inline u32 RTW_SN_DELTA(u32 x, u32 y)
156 {
157 	return x >= y ? x - y : y - x;
158 }
159 
160 #define rtw_net_traversal_jiffies(adapter) \
161 	rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPnetDiameterTraversalTime)
162 #define rtw_default_lifetime(adapter) \
163 	RTW_MSEC_TO_TU(adapter->mesh_cfg.dot11MeshHWMPactivePathTimeout)
164 #define rtw_min_preq_int_jiff(adapter) \
165 	(rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPpreqMinInterval))
166 #define rtw_max_preq_retries(adapter) (adapter->mesh_cfg.dot11MeshHWMPmaxPREQretries)
167 #define rtw_disc_timeout_jiff(adapter) \
168 	rtw_ms_to_systime(adapter->mesh_cfg.min_discovery_timeout)
169 #define rtw_root_path_confirmation_jiffies(adapter) \
170 	rtw_ms_to_systime(adapter->mesh_cfg.dot11MeshHWMPconfirmationInterval)
171 
rtw_ether_addr_equal(const u8 * addr1,const u8 * addr2)172 static inline BOOLEAN rtw_ether_addr_equal(const u8 *addr1, const u8 *addr2)
173 {
174 	return _rtw_memcmp(addr1, addr2, ETH_ALEN);
175 }
176 
177 #ifdef PLATFORM_LINUX
178 #define rtw_print_ratelimit()	printk_ratelimit()
179 #define rtw_mod_timer(ptimer, expires) mod_timer(&(ptimer)->timer, expires)
180 #else
181 
182 #endif
183 
184 #define RTW_MESH_EWMA_PRECISION 20
185 #define RTW_MESH_EWMA_WEIGHT_RCP 8
186 #define RTW_TOTAL_PKT_MIN_THRESHOLD 1
rtw_ewma_err_rate_init(struct rtw_ewma_err_rate * e)187 inline void rtw_ewma_err_rate_init(struct rtw_ewma_err_rate *e)
188 {
189 	e->internal = 0;
190 }
rtw_ewma_err_rate_read(struct rtw_ewma_err_rate * e)191 inline unsigned long rtw_ewma_err_rate_read(struct rtw_ewma_err_rate *e)
192 {
193 	return e->internal >> (RTW_MESH_EWMA_PRECISION);
194 }
rtw_ewma_err_rate_add(struct rtw_ewma_err_rate * e,unsigned long val)195 inline void rtw_ewma_err_rate_add(struct rtw_ewma_err_rate *e,
196 				  unsigned long val)
197 {
198 	unsigned long internal = e->internal;
199 	unsigned long weight_rcp = rtw_ilog2(RTW_MESH_EWMA_WEIGHT_RCP);
200 	unsigned long precision = RTW_MESH_EWMA_PRECISION;
201 
202 	(e->internal) = internal ? (((internal << weight_rcp) - internal) +
203 			(val << precision)) >> weight_rcp :
204 			(val << precision);
205 }
206 
207 static const u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
208 
rtw_mesh_path_sel_frame_tx(enum rtw_mpath_frame_type mpath_action,u8 flags,const u8 * originator_addr,u32 originator_sn,u8 target_flags,const u8 * target,u32 target_sn,const u8 * da,u8 hopcount,u8 ttl,u32 lifetime,u32 metric,u32 preq_id,_adapter * adapter)209 static int rtw_mesh_path_sel_frame_tx(enum rtw_mpath_frame_type mpath_action, u8 flags,
210 				      const u8 *originator_addr, u32 originator_sn,
211 				      u8 target_flags, const u8 *target,
212 				      u32 target_sn, const u8 *da, u8 hopcount, u8 ttl,
213 				      u32 lifetime, u32 metric, u32 preq_id,
214 				      _adapter *adapter)
215 {
216 	struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
217 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
218 	struct xmit_frame *pmgntframe = NULL;
219 	struct rtw_ieee80211_hdr *pwlanhdr = NULL;
220 	struct pkt_attrib *pattrib = NULL;
221 	u8 category = RTW_WLAN_CATEGORY_MESH;
222 	u8 action = RTW_ACT_MESH_HWMP_PATH_SELECTION;
223 	u16 *fctrl = NULL;
224 	u8 *pos, ie_len;
225 
226 
227 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
228 	if (pmgntframe == NULL)
229 		return -1;
230 
231 	pattrib = &pmgntframe->attrib;
232 	update_mgntframe_attrib(adapter, pattrib);
233 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
234 
235 	pos = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
236 	pwlanhdr = (struct rtw_ieee80211_hdr *)pos;
237 
238 
239 	fctrl = &(pwlanhdr->frame_ctl);
240 	*(fctrl) = 0;
241 
242 	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
243 	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
244 	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(adapter), ETH_ALEN);
245 
246 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
247 	pmlmeext->mgnt_seq++;
248 	set_frame_sub_type(pos, WIFI_ACTION);
249 
250 	pos += sizeof(struct rtw_ieee80211_hdr_3addr);
251 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
252 
253 	pos = rtw_set_fixed_ie(pos, 1, &(category), &(pattrib->pktlen));
254 	pos = rtw_set_fixed_ie(pos, 1, &(action), &(pattrib->pktlen));
255 
256 	switch (mpath_action) {
257 	case RTW_MPATH_PREQ:
258 		RTW_HWMP_DBG("sending PREQ to "MAC_FMT"\n", MAC_ARG(target));
259 		ie_len = 37;
260 		pattrib->pktlen += (ie_len + 2);
261 		*pos++ = WLAN_EID_PREQ;
262 		break;
263 	case RTW_MPATH_PREP:
264 		RTW_HWMP_DBG("sending PREP to "MAC_FMT"\n", MAC_ARG(originator_addr));
265 		ie_len = 31;
266 		pattrib->pktlen += (ie_len + 2);
267 		*pos++ = WLAN_EID_PREP;
268 		break;
269 	case RTW_MPATH_RANN:
270 		RTW_HWMP_DBG("sending RANN from "MAC_FMT"\n", MAC_ARG(originator_addr));
271 		ie_len = sizeof(struct rtw_ieee80211_rann_ie);
272 		pattrib->pktlen += (ie_len + 2);
273 		*pos++ = WLAN_EID_RANN;
274 		break;
275 	default:
276 		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
277 		rtw_free_xmitframe(pxmitpriv, pmgntframe);
278 		return _FAIL;
279 	}
280 	*pos++ = ie_len;
281 	*pos++ = flags;
282 	*pos++ = hopcount;
283 	*pos++ = ttl;
284 	if (mpath_action == RTW_MPATH_PREP) {
285 		_rtw_memcpy(pos, target, ETH_ALEN);
286 		pos += ETH_ALEN;
287 		*(u32 *)pos = cpu_to_le32(target_sn);
288 		pos += 4;
289 	} else {
290 		if (mpath_action == RTW_MPATH_PREQ) {
291 			*(u32 *)pos = cpu_to_le32(preq_id);
292 			pos += 4;
293 		}
294 		_rtw_memcpy(pos, originator_addr, ETH_ALEN);
295 		pos += ETH_ALEN;
296 		*(u32 *)pos = cpu_to_le32(originator_sn);
297 		pos += 4;
298 	}
299 	*(u32 *)pos = cpu_to_le32(lifetime);
300 	pos += 4;
301 	*(u32 *)pos = cpu_to_le32(metric);
302 	pos += 4;
303 	if (mpath_action == RTW_MPATH_PREQ) {
304 		*pos++ = 1; /* support only 1 destination now */
305 		*pos++ = target_flags;
306 		_rtw_memcpy(pos, target, ETH_ALEN);
307 		pos += ETH_ALEN;
308 		*(u32 *)pos = cpu_to_le32(target_sn);
309 		pos += 4;
310 	} else if (mpath_action == RTW_MPATH_PREP) {
311 		_rtw_memcpy(pos, originator_addr, ETH_ALEN);
312 		pos += ETH_ALEN;
313 		*(u32 *)pos = cpu_to_le32(originator_sn);
314 		pos += 4;
315 	}
316 
317 	pattrib->last_txcmdsz = pattrib->pktlen;
318 	dump_mgntframe(adapter, pmgntframe);
319 	return 0;
320 }
321 
rtw_mesh_path_error_tx(_adapter * adapter,u8 ttl,const u8 * target,u32 target_sn,u16 perr_reason_code,const u8 * ra)322 int rtw_mesh_path_error_tx(_adapter *adapter,
323 			   u8 ttl, const u8 *target, u32 target_sn,
324 			   u16 perr_reason_code, const u8 *ra)
325 {
326 
327 	struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
328 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
329 	struct xmit_frame *pmgntframe = NULL;
330 	struct rtw_ieee80211_hdr *pwlanhdr = NULL;
331 	struct pkt_attrib *pattrib = NULL;
332 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
333 	u8 category = RTW_WLAN_CATEGORY_MESH;
334 	u8 action = RTW_ACT_MESH_HWMP_PATH_SELECTION;
335 	u8 *pos, ie_len;
336 	u16 *fctrl = NULL;
337 
338 	if (rtw_time_before(rtw_get_current_time(), minfo->next_perr))
339 		return -1;
340 
341 	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
342 	if (pmgntframe == NULL)
343 		return -1;
344 
345 	pattrib = &pmgntframe->attrib;
346 	update_mgntframe_attrib(adapter, pattrib);
347 	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
348 
349 	pos = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
350 	pwlanhdr = (struct rtw_ieee80211_hdr *)pos;
351 
352 	fctrl = &(pwlanhdr->frame_ctl);
353 	*(fctrl) = 0;
354 
355 	_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
356 	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(adapter), ETH_ALEN);
357 	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(adapter), ETH_ALEN);
358 
359 	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
360 	pmlmeext->mgnt_seq++;
361 	set_frame_sub_type(pos, WIFI_ACTION);
362 
363 	pos += sizeof(struct rtw_ieee80211_hdr_3addr);
364 	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
365 
366 	pos = rtw_set_fixed_ie(pos, 1, &(category), &(pattrib->pktlen));
367 	pos = rtw_set_fixed_ie(pos, 1, &(action), &(pattrib->pktlen));
368 
369 	ie_len = 15;
370 	pattrib->pktlen += (2 + ie_len);
371 	*pos++ = WLAN_EID_PERR;
372 	*pos++ = ie_len;
373 	/* ttl */
374 	*pos++ = ttl;
375 	/* The Number of Destinations N */
376 	*pos++ = 1;
377 	/* Flags format | B7 | B6 | B5:B0 | = | rsvd | AE | rsvd | */
378 	*pos = 0;
379 	pos++;
380 	_rtw_memcpy(pos, target, ETH_ALEN);
381 	pos += ETH_ALEN;
382 	*(u32 *)pos = cpu_to_le32(target_sn);
383 	pos += 4;
384 	*(u16 *)pos = cpu_to_le16(perr_reason_code);
385 
386 	adapter->mesh_info.next_perr = RTW_TU_TO_EXP_TIME(
387 				adapter->mesh_cfg.dot11MeshHWMPperrMinInterval);
388 	pattrib->last_txcmdsz = pattrib->pktlen;
389 	/* Send directly. Rewrite it if deferred tx is needed */
390 	dump_mgntframe(adapter, pmgntframe);
391 
392 	RTW_HWMP_DBG("TX PERR toward "MAC_FMT", ra = "MAC_FMT"\n", MAC_ARG(target), MAC_ARG(ra));
393 
394 	return 0;
395 }
396 
rtw_airtime_link_metric_get(_adapter * adapter,struct sta_info * sta)397 static u32 rtw_airtime_link_metric_get(_adapter *adapter, struct sta_info *sta)
398 {
399 	struct dm_struct *dm = adapter_to_phydm(adapter);
400 	int device_constant = phydm_get_plcp(dm, sta->cmn.mac_id) << RTW_ARITH_SHIFT;
401 	u32 test_frame_len = RTW_TEST_FRAME_LEN << RTW_ARITH_SHIFT;
402 	u32 s_unit = 1 << RTW_ARITH_SHIFT;
403 	u32 err;
404 	u16 rate;
405 	u32 tx_time, estimated_retx;
406 	u64 result;
407 	/* The fail_avg should <= 100 here */
408 	u32 fail_avg = (u32)rtw_ewma_err_rate_read(&sta->metrics.err_rate);
409 
410 	if (fail_avg > RTW_LINK_FAIL_THRESH)
411 		return RTW_MAX_METRIC;
412 
413 	rate = sta->metrics.data_rate;
414 	/* rate unit is 100Kbps, min rate = 10 */
415 	if (rate < 10) {
416 		RTW_HWMP_INFO("rate = %d\n", rate);
417 		return RTW_MAX_METRIC;
418 	}
419 
420 	err = (fail_avg << RTW_ARITH_SHIFT) / 100;
421 
422 	/* test_frame_len*10 to adjust the unit of rate(100kbps/unit) */
423 	tx_time = (device_constant + 10 * test_frame_len / rate);
424 	estimated_retx = ((1 << (2 * RTW_ARITH_SHIFT)) / (s_unit - err));
425 	result = (tx_time * estimated_retx) >> (2 * RTW_ARITH_SHIFT);
426 	/* Convert us to 0.01 TU(10.24us). x/10.24 = x*100/1024 */
427 	result = (result * 100) >> 10;
428 
429 	return (u32)result;
430 }
431 
rtw_ieee80211s_update_metric(_adapter * adapter,u8 mac_id,u8 per,u8 rate,u8 bw,u8 total_pkt)432 void rtw_ieee80211s_update_metric(_adapter *adapter, u8 mac_id,
433 				  u8 per, u8 rate,
434 				  u8 bw, u8 total_pkt)
435 {
436 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
437 	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
438 	struct sta_info *sta;
439 	u8 rate_idx;
440 	u8 sgi;
441 
442 	sta = macid_ctl->sta[mac_id];
443 	if (!sta)
444 		return;
445 
446 	/* if RA, use reported rate */
447 	if (adapter->fix_rate == 0xff) {
448 		rate_idx = rate & 0x7f;
449 		sgi = rate >> 7;
450 	} else {
451 		rate_idx = adapter->fix_rate & 0x7f;
452 		sgi = adapter->fix_rate >> 7;
453 	}
454 	sta->metrics.data_rate = rtw_desc_rate_to_bitrate(bw, rate_idx, sgi);
455 
456 	if (total_pkt < RTW_TOTAL_PKT_MIN_THRESHOLD)
457 		return;
458 
459 	/* TBD: sta->metrics.overhead = phydm_get_plcp(void *dm_void, u16 macid); */
460 	sta->metrics.total_pkt = total_pkt;
461 
462 	rtw_ewma_err_rate_add(&sta->metrics.err_rate, per);
463 	if (rtw_ewma_err_rate_read(&sta->metrics.err_rate) >
464 			RTW_LINK_FAIL_THRESH)
465 		rtw_mesh_plink_broken(sta);
466 }
467 
rtw_hwmp_preq_frame_process(_adapter * adapter,struct rtw_ieee80211_hdr_3addr * mgmt,const u8 * preq_elem,u32 originator_metric)468 static void rtw_hwmp_preq_frame_process(_adapter *adapter,
469 					struct rtw_ieee80211_hdr_3addr *mgmt,
470 					const u8 *preq_elem, u32 originator_metric)
471 {
472 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
473 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
474 	struct rtw_mesh_path *path = NULL;
475 	const u8 *target_addr, *originator_addr;
476 	const u8 *da;
477 	u8 target_flags, ttl, flags, to_gate_ask = 0;
478 	u32 originator_sn, target_sn, lifetime, target_metric = 0;
479 	BOOLEAN reply = _FALSE;
480 	BOOLEAN forward = _TRUE;
481 	BOOLEAN preq_is_gate;
482 
483 	/* Update target SN, if present */
484 	target_addr = RTW_PREQ_IE_TARGET_ADDR(preq_elem);
485 	originator_addr = RTW_PREQ_IE_ORIG_ADDR(preq_elem);
486 	target_sn = RTW_PREQ_IE_TARGET_SN(preq_elem);
487 	originator_sn = RTW_PREQ_IE_ORIG_SN(preq_elem);
488 	target_flags = RTW_PREQ_IE_TARGET_F(preq_elem);
489 	/* PREQ gate announcements */
490 	flags = RTW_PREQ_IE_FLAGS(preq_elem);
491 	preq_is_gate = !!(flags & RTW_IEEE80211_PREQ_IS_GATE_FLAG);
492 
493 	RTW_HWMP_DBG("received PREQ from "MAC_FMT"\n", MAC_ARG(originator_addr));
494 
495 	if (rtw_ether_addr_equal(target_addr, adapter_mac_addr(adapter))) {
496 		RTW_HWMP_DBG("PREQ is for us\n");
497 #ifdef CONFIG_RTW_MESH_ON_DMD_GANN
498 		rtw_rcu_read_lock();
499 		path = rtw_mesh_path_lookup(adapter, originator_addr);
500 		if (path) {
501 			if (preq_is_gate)
502 				rtw_mesh_path_add_gate(path);
503 			else if (path->is_gate) {
504 				enter_critical_bh(&path->state_lock);
505 				rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
506 				exit_critical_bh(&path->state_lock);
507 			}
508 		}
509 		path = NULL;
510 		rtw_rcu_read_unlock();
511 #endif
512 		forward = _FALSE;
513 		reply = _TRUE;
514 		to_gate_ask = 1;
515 		target_metric = 0;
516 		if (rtw_time_after(rtw_get_current_time(), minfo->last_sn_update +
517 					rtw_net_traversal_jiffies(adapter)) ||
518 		    rtw_time_before(rtw_get_current_time(), minfo->last_sn_update)) {
519 			++minfo->sn;
520 			minfo->last_sn_update = rtw_get_current_time();
521 		}
522 		target_sn = minfo->sn;
523 	} else if (is_broadcast_mac_addr(target_addr) &&
524 		   (target_flags & RTW_IEEE80211_PREQ_TO_FLAG)) {
525 		rtw_rcu_read_lock();
526 		path = rtw_mesh_path_lookup(adapter, originator_addr);
527 		if (path) {
528 			if (flags & RTW_IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
529 				reply = _TRUE;
530 				target_addr = adapter_mac_addr(adapter);
531 				target_sn = ++minfo->sn;
532 				target_metric = 0;
533 				minfo->last_sn_update = rtw_get_current_time();
534 			}
535 
536 			if (preq_is_gate) {
537 				lifetime = RTW_PREQ_IE_LIFETIME(preq_elem);
538 				path->gate_ann_int = lifetime;
539 				path->gate_asked = false;
540 				rtw_mesh_path_add_gate(path);
541 			} else if (path->is_gate) {
542 				enter_critical_bh(&path->state_lock);
543 				rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
544 				exit_critical_bh(&path->state_lock);
545 			}
546 		}
547 		rtw_rcu_read_unlock();
548 	} else {
549 		rtw_rcu_read_lock();
550 #ifdef CONFIG_RTW_MESH_ON_DMD_GANN
551 		path = rtw_mesh_path_lookup(adapter, originator_addr);
552 		if (path) {
553 			if (preq_is_gate)
554 				rtw_mesh_path_add_gate(path);
555 			else if (path->is_gate) {
556 				enter_critical_bh(&path->state_lock);
557 				rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
558 				exit_critical_bh(&path->state_lock);
559 			}
560 		}
561 		path = NULL;
562 #endif
563 		path = rtw_mesh_path_lookup(adapter, target_addr);
564 		if (path) {
565 			if ((!(path->flags & RTW_MESH_PATH_SN_VALID)) ||
566 					RTW_SN_LT(path->sn, target_sn)) {
567 				path->sn = target_sn;
568 				path->flags |= RTW_MESH_PATH_SN_VALID;
569 			} else if ((!(target_flags & RTW_IEEE80211_PREQ_TO_FLAG)) &&
570 					(path->flags & RTW_MESH_PATH_ACTIVE)) {
571 				reply = _TRUE;
572 				target_metric = path->metric;
573 				target_sn = path->sn;
574 				/* Case E2 of sec 13.10.9.3 IEEE 802.11-2012*/
575 				target_flags |= RTW_IEEE80211_PREQ_TO_FLAG;
576 			}
577 		}
578 		rtw_rcu_read_unlock();
579 	}
580 
581 	if (reply) {
582 		lifetime = RTW_PREQ_IE_LIFETIME(preq_elem);
583 		ttl = mshcfg->element_ttl;
584 		if (ttl != 0 && !to_gate_ask) {
585 			RTW_HWMP_DBG("replying to the PREQ\n");
586 			rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREP, 0, originator_addr,
587 						   originator_sn, 0, target_addr,
588 						   target_sn, mgmt->addr2, 0, ttl,
589 						   lifetime, target_metric, 0,
590 						   adapter);
591 		} else if (ttl != 0 && to_gate_ask) {
592 			RTW_HWMP_DBG("replying to the PREQ (PREQ for us)\n");
593 			if (mshcfg->dot11MeshGateAnnouncementProtocol) {
594 				/* BIT 7 is used to identify the prep is from mesh gate */
595 				to_gate_ask = RTW_IEEE80211_PREQ_IS_GATE_FLAG | BIT(7);
596 			} else {
597 				to_gate_ask = 0;
598 			}
599 
600 			rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREP, to_gate_ask, originator_addr,
601 						   originator_sn, 0, target_addr,
602 						   target_sn, mgmt->addr2, 0, ttl,
603 						   lifetime, target_metric, 0,
604 						   adapter);
605 		} else {
606 			minfo->mshstats.dropped_frames_ttl++;
607 		}
608 	}
609 
610 	if (forward && mshcfg->dot11MeshForwarding) {
611 		u32 preq_id;
612 		u8 hopcount;
613 
614 		ttl = RTW_PREQ_IE_TTL(preq_elem);
615 		lifetime = RTW_PREQ_IE_LIFETIME(preq_elem);
616 		if (ttl <= 1) {
617 			minfo->mshstats.dropped_frames_ttl++;
618 			return;
619 		}
620 		RTW_HWMP_DBG("forwarding the PREQ from "MAC_FMT"\n", MAC_ARG(originator_addr));
621 		--ttl;
622 		preq_id = RTW_PREQ_IE_PREQ_ID(preq_elem);
623 		hopcount = RTW_PREQ_IE_HOPCOUNT(preq_elem) + 1;
624 		da = (path && path->is_root) ?
625 			path->rann_snd_addr : bcast_addr;
626 
627 		if (flags & RTW_IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
628 			target_addr = RTW_PREQ_IE_TARGET_ADDR(preq_elem);
629 			target_sn = RTW_PREQ_IE_TARGET_SN(preq_elem);
630 		}
631 
632 		rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREQ, flags, originator_addr,
633 					   originator_sn, target_flags, target_addr,
634 					   target_sn, da, hopcount, ttl, lifetime,
635 					   originator_metric, preq_id, adapter);
636 		if (!is_multicast_mac_addr(da))
637 			minfo->mshstats.fwded_unicast++;
638 		else
639 			minfo->mshstats.fwded_mcast++;
640 		minfo->mshstats.fwded_frames++;
641 	}
642 }
643 
644 static inline struct sta_info *
rtw_next_hop_deref_protected(struct rtw_mesh_path * path)645 rtw_next_hop_deref_protected(struct rtw_mesh_path *path)
646 {
647 	return rtw_rcu_dereference_protected(path->next_hop,
648 					 rtw_lockdep_is_held(&path->state_lock));
649 }
650 
rtw_hwmp_prep_frame_process(_adapter * adapter,struct rtw_ieee80211_hdr_3addr * mgmt,const u8 * prep_elem,u32 metric)651 static void rtw_hwmp_prep_frame_process(_adapter *adapter,
652 					struct rtw_ieee80211_hdr_3addr *mgmt,
653 					const u8 *prep_elem, u32 metric)
654 {
655 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
656 	struct rtw_mesh_stats *mshstats = &adapter->mesh_info.mshstats;
657 	struct rtw_mesh_path *path;
658 	const u8 *target_addr, *originator_addr;
659 	u8 ttl, hopcount, flags;
660 	u8 next_hop[ETH_ALEN];
661 	u32 target_sn, originator_sn, lifetime;
662 
663 	RTW_HWMP_DBG("received PREP from "MAC_FMT"\n",
664 		  MAC_ARG(RTW_PREP_IE_TARGET_ADDR(prep_elem)));
665 
666 	originator_addr = RTW_PREP_IE_ORIG_ADDR(prep_elem);
667 	if (rtw_ether_addr_equal(originator_addr, adapter_mac_addr(adapter))) {
668 		/* destination, no forwarding required */
669 		rtw_rcu_read_lock();
670 		target_addr = RTW_PREP_IE_TARGET_ADDR(prep_elem);
671 		path = rtw_mesh_path_lookup(adapter, target_addr);
672 		if (path && path->gate_asked) {
673 			flags = RTW_PREP_IE_FLAGS(prep_elem);
674 			if (flags & BIT(7)) {
675 				enter_critical_bh(&path->state_lock);
676 				path->gate_asked = false;
677 				exit_critical_bh(&path->state_lock);
678 				if (!(flags & RTW_IEEE80211_PREQ_IS_GATE_FLAG)) {
679 					enter_critical_bh(&path->state_lock);
680 					rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
681 					exit_critical_bh(&path->state_lock);
682 				}
683 			}
684 		}
685 
686 		rtw_rcu_read_unlock();
687 		return;
688 	}
689 
690 	if (!mshcfg->dot11MeshForwarding)
691 		return;
692 
693 	ttl = RTW_PREP_IE_TTL(prep_elem);
694 	if (ttl <= 1) {
695 		mshstats->dropped_frames_ttl++;
696 		return;
697 	}
698 
699 	rtw_rcu_read_lock();
700 	path = rtw_mesh_path_lookup(adapter, originator_addr);
701 	if (path)
702 		enter_critical_bh(&path->state_lock);
703 	else
704 		goto fail;
705 	if (!(path->flags & RTW_MESH_PATH_ACTIVE)) {
706 		exit_critical_bh(&path->state_lock);
707 		goto fail;
708 	}
709 	_rtw_memcpy(next_hop, rtw_next_hop_deref_protected(path)->cmn.mac_addr, ETH_ALEN);
710 	exit_critical_bh(&path->state_lock);
711 	--ttl;
712 	flags = RTW_PREP_IE_FLAGS(prep_elem);
713 	lifetime = RTW_PREP_IE_LIFETIME(prep_elem);
714 	hopcount = RTW_PREP_IE_HOPCOUNT(prep_elem) + 1;
715 	target_addr = RTW_PREP_IE_TARGET_ADDR(prep_elem);
716 	target_sn = RTW_PREP_IE_TARGET_SN(prep_elem);
717 	originator_sn = RTW_PREP_IE_ORIG_SN(prep_elem);
718 
719 	rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREP, flags, originator_addr, originator_sn, 0,
720 				   target_addr, target_sn, next_hop, hopcount,
721 				   ttl, lifetime, metric, 0, adapter);
722 	rtw_rcu_read_unlock();
723 
724 	mshstats->fwded_unicast++;
725 	mshstats->fwded_frames++;
726 	return;
727 
728 fail:
729 	rtw_rcu_read_unlock();
730 	mshstats->dropped_frames_no_route++;
731 }
732 
rtw_hwmp_perr_frame_process(_adapter * adapter,struct rtw_ieee80211_hdr_3addr * mgmt,const u8 * perr_elem)733 static void rtw_hwmp_perr_frame_process(_adapter *adapter,
734 					struct rtw_ieee80211_hdr_3addr *mgmt,
735 					const u8 *perr_elem)
736 {
737 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
738 	struct rtw_mesh_stats *mshstats = &adapter->mesh_info.mshstats;
739 	struct rtw_mesh_path *path;
740 	u8 ttl;
741 	const u8 *ta, *target_addr;
742 	u32 target_sn;
743 	u16 perr_reason_code;
744 
745 	ta = mgmt->addr2;
746 	ttl = RTW_PERR_IE_TTL(perr_elem);
747 	if (ttl <= 1) {
748 		mshstats->dropped_frames_ttl++;
749 		return;
750 	}
751 	ttl--;
752 	target_addr = RTW_PERR_IE_TARGET_ADDR(perr_elem);
753 	target_sn = RTW_PERR_IE_TARGET_SN(perr_elem);
754 	perr_reason_code = RTW_PERR_IE_TARGET_RCODE(perr_elem);
755 
756 	RTW_HWMP_DBG("received PERR toward target "MAC_FMT"\n", MAC_ARG(target_addr));
757 
758 	rtw_rcu_read_lock();
759 	path = rtw_mesh_path_lookup(adapter, target_addr);
760 	if (path) {
761 		struct sta_info *sta;
762 
763 		enter_critical_bh(&path->state_lock);
764 		sta = rtw_next_hop_deref_protected(path);
765 		if (path->flags & RTW_MESH_PATH_ACTIVE &&
766 		    rtw_ether_addr_equal(ta, sta->cmn.mac_addr) &&
767 		    !(path->flags & RTW_MESH_PATH_FIXED) &&
768 		    (!(path->flags & RTW_MESH_PATH_SN_VALID) ||
769 		    RTW_SN_GT(target_sn, path->sn)  || target_sn == 0)) {
770 			path->flags &= ~RTW_MESH_PATH_ACTIVE;
771 			if (target_sn != 0)
772 				path->sn = target_sn;
773 			else
774 				path->sn += 1;
775 			exit_critical_bh(&path->state_lock);
776 			if (!mshcfg->dot11MeshForwarding)
777 				goto endperr;
778 			rtw_mesh_path_error_tx(adapter, ttl, target_addr,
779 					       target_sn, perr_reason_code,
780 					       bcast_addr);
781 		} else
782 			exit_critical_bh(&path->state_lock);
783 	}
784 endperr:
785 	rtw_rcu_read_unlock();
786 }
787 
rtw_hwmp_rann_frame_process(_adapter * adapter,struct rtw_ieee80211_hdr_3addr * mgmt,const struct rtw_ieee80211_rann_ie * rann)788 static void rtw_hwmp_rann_frame_process(_adapter *adapter,
789 					struct rtw_ieee80211_hdr_3addr *mgmt,
790 					const struct rtw_ieee80211_rann_ie *rann)
791 {
792 	struct sta_info *sta;
793 	struct sta_priv *pstapriv = &adapter->stapriv;
794 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
795 	struct rtw_mesh_stats *mshstats = &adapter->mesh_info.mshstats;
796 	struct rtw_mesh_path *path;
797 	u8 ttl, flags, hopcount;
798 	const u8 *originator_addr;
799 	u32 originator_sn, metric, metric_txsta, interval;
800 	BOOLEAN root_is_gate;
801 
802 	ttl = rann->rann_ttl;
803 	flags = rann->rann_flags;
804 	root_is_gate = !!(flags & RTW_RANN_FLAG_IS_GATE);
805 	originator_addr = rann->rann_addr;
806 	originator_sn = le32_to_cpu(rann->rann_seq);
807 	interval = le32_to_cpu(rann->rann_interval);
808 	hopcount = rann->rann_hopcount;
809 	hopcount++;
810 	metric = le32_to_cpu(rann->rann_metric);
811 
812 	/*  Ignore our own RANNs */
813 	if (rtw_ether_addr_equal(originator_addr, adapter_mac_addr(adapter)))
814 		return;
815 
816 	RTW_HWMP_DBG("received RANN from "MAC_FMT" via neighbour "MAC_FMT" (is_gate=%d)\n",
817 		  MAC_ARG(originator_addr), MAC_ARG(mgmt->addr2), root_is_gate);
818 
819 	rtw_rcu_read_lock();
820 	sta = rtw_get_stainfo(pstapriv, mgmt->addr2);
821 	if (!sta) {
822 		rtw_rcu_read_unlock();
823 		return;
824 	}
825 
826 	metric_txsta = rtw_airtime_link_metric_get(adapter, sta);
827 
828 	path = rtw_mesh_path_lookup(adapter, originator_addr);
829 	if (!path) {
830 		path = rtw_mesh_path_add(adapter, originator_addr);
831 		if (IS_ERR(path)) {
832 			rtw_rcu_read_unlock();
833 			mshstats->dropped_frames_no_route++;
834 			return;
835 		}
836 	}
837 
838 	if (!(RTW_SN_LT(path->sn, originator_sn)) &&
839 	    !(path->sn == originator_sn && metric < path->rann_metric)) {
840 		rtw_rcu_read_unlock();
841 		return;
842 	}
843 
844 	if ((!(path->flags & (RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVING)) ||
845 	     (rtw_time_after(rtw_get_current_time(), path->last_preq_to_root +
846 				  rtw_root_path_confirmation_jiffies(adapter)) ||
847 	     rtw_time_before(rtw_get_current_time(), path->last_preq_to_root))) &&
848 	     !(path->flags & RTW_MESH_PATH_FIXED) && (ttl != 0)) {
849 		u8 preq_node_flag = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_REFRESH;
850 
851 		RTW_HWMP_DBG("time to refresh root path "MAC_FMT"\n",
852 			  MAC_ARG(originator_addr));
853 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
854 		if (RTW_SN_LT(path->sn, originator_sn) &&
855 		    (path->rann_metric + mshcfg->sane_metric_delta < metric) &&
856 		    _rtw_memcmp(bcast_addr, path->rann_snd_addr, ETH_ALEN) == _FALSE) {
857 			RTW_HWMP_DBG("Trigger additional check for root "
858 				     "confirm PREQ. rann_snd_addr = "MAC_FMT
859 				     "add_chk_rann_snd_addr= "MAC_FMT"\n",
860 					MAC_ARG(mgmt->addr2),
861 					MAC_ARG(path->rann_snd_addr));
862 			_rtw_memcpy(path->add_chk_rann_snd_addr,
863 				    path->rann_snd_addr, ETH_ALEN);
864 			preq_node_flag |= RTW_PREQ_Q_F_CHK;
865 
866 		}
867 #endif
868 		rtw_mesh_queue_preq(path, preq_node_flag);
869 		path->last_preq_to_root = rtw_get_current_time();
870 	}
871 
872 	path->sn = originator_sn;
873 	path->rann_metric = metric + metric_txsta;
874 	path->is_root = _TRUE;
875 	/* Recording RANNs sender address to send individually
876 	 * addressed PREQs destined for root mesh STA */
877 	_rtw_memcpy(path->rann_snd_addr, mgmt->addr2, ETH_ALEN);
878 
879 	if (root_is_gate) {
880 		path->gate_ann_int = interval;
881 		path->gate_asked = false;
882 		rtw_mesh_path_add_gate(path);
883 	} else if (path->is_gate) {
884 		enter_critical_bh(&path->state_lock);
885 		rtw_mesh_gate_del(adapter->mesh_info.mesh_paths, path);
886 		exit_critical_bh(&path->state_lock);
887 	}
888 
889 	if (ttl <= 1) {
890 		mshstats->dropped_frames_ttl++;
891 		rtw_rcu_read_unlock();
892 		return;
893 	}
894 	ttl--;
895 
896 	if (mshcfg->dot11MeshForwarding) {
897 		rtw_mesh_path_sel_frame_tx(RTW_MPATH_RANN, flags, originator_addr,
898 					   originator_sn, 0, NULL, 0, bcast_addr,
899 					   hopcount, ttl, interval,
900 					   metric + metric_txsta, 0, adapter);
901 	}
902 
903 	rtw_rcu_read_unlock();
904 }
905 
rtw_hwmp_route_info_get(_adapter * adapter,struct rtw_ieee80211_hdr_3addr * mgmt,const u8 * hwmp_ie,enum rtw_mpath_frame_type action)906 static u32 rtw_hwmp_route_info_get(_adapter *adapter,
907 				   struct rtw_ieee80211_hdr_3addr *mgmt,
908 				   const u8 *hwmp_ie, enum rtw_mpath_frame_type action)
909 {
910 	struct rtw_mesh_path *path;
911 	struct sta_priv *pstapriv = &adapter->stapriv;
912 	struct sta_info *sta;
913 	BOOLEAN fresh_info;
914 	const u8 *originator_addr, *ta;
915 	u32 originator_sn, originator_metric;
916 	unsigned long originator_lifetime, exp_time;
917 	u32 last_hop_metric, new_metric;
918 	BOOLEAN process = _TRUE;
919 
920 	rtw_rcu_read_lock();
921 	sta = rtw_get_stainfo(pstapriv, mgmt->addr2);
922 	if (!sta) {
923 		rtw_rcu_read_unlock();
924 		return 0;
925 	}
926 
927 	last_hop_metric = rtw_airtime_link_metric_get(adapter, sta);
928 	/* Update and check originator routing info */
929 	fresh_info = _TRUE;
930 
931 	switch (action) {
932 	case RTW_MPATH_PREQ:
933 		originator_addr = RTW_PREQ_IE_ORIG_ADDR(hwmp_ie);
934 		originator_sn = RTW_PREQ_IE_ORIG_SN(hwmp_ie);
935 		originator_lifetime = RTW_PREQ_IE_LIFETIME(hwmp_ie);
936 		originator_metric = RTW_PREQ_IE_METRIC(hwmp_ie);
937 		break;
938 	case RTW_MPATH_PREP:
939 		/* Note: For coding, the naming is not consist with spec */
940 		originator_addr = RTW_PREP_IE_TARGET_ADDR(hwmp_ie);
941 		originator_sn = RTW_PREP_IE_TARGET_SN(hwmp_ie);
942 		originator_lifetime = RTW_PREP_IE_LIFETIME(hwmp_ie);
943 		originator_metric = RTW_PREP_IE_METRIC(hwmp_ie);
944 		break;
945 	default:
946 		rtw_rcu_read_unlock();
947 		return 0;
948 	}
949 	new_metric = originator_metric + last_hop_metric;
950 	if (new_metric < originator_metric)
951 		new_metric = RTW_MAX_METRIC;
952 	exp_time = RTW_TU_TO_EXP_TIME(originator_lifetime);
953 
954 	if (rtw_ether_addr_equal(originator_addr, adapter_mac_addr(adapter))) {
955 		process = _FALSE;
956 		fresh_info = _FALSE;
957 	} else {
958 		path = rtw_mesh_path_lookup(adapter, originator_addr);
959 		if (path) {
960 			enter_critical_bh(&path->state_lock);
961 			if (path->flags & RTW_MESH_PATH_FIXED)
962 				fresh_info = _FALSE;
963 			else if ((path->flags & RTW_MESH_PATH_ACTIVE) &&
964 			    (path->flags & RTW_MESH_PATH_SN_VALID)) {
965 				if (RTW_SN_GT(path->sn, originator_sn) ||
966 				    (path->sn == originator_sn &&
967 				     new_metric >= path->metric)) {
968 					process = _FALSE;
969 					fresh_info = _FALSE;
970 				}
971 			} else if (!(path->flags & RTW_MESH_PATH_ACTIVE)) {
972 				BOOLEAN have_sn, newer_sn, bounced;
973 
974 				have_sn = path->flags & RTW_MESH_PATH_SN_VALID;
975 				newer_sn = have_sn && RTW_SN_GT(originator_sn, path->sn);
976 				bounced = have_sn &&
977 					  (RTW_SN_DELTA(originator_sn, path->sn) >
978 							RTW_MAX_SANE_SN_DELTA);
979 
980 				if (!have_sn || newer_sn) {
981 				} else if (bounced) {
982 				} else {
983 					process = _FALSE;
984 					fresh_info = _FALSE;
985 				}
986 			}
987 		} else {
988 			path = rtw_mesh_path_add(adapter, originator_addr);
989 			if (IS_ERR(path)) {
990 				rtw_rcu_read_unlock();
991 				return 0;
992 			}
993 			enter_critical_bh(&path->state_lock);
994 		}
995 
996 		if (fresh_info) {
997 			rtw_mesh_path_assign_nexthop(path, sta);
998 			path->flags |= RTW_MESH_PATH_SN_VALID;
999 			path->metric = new_metric;
1000 			path->sn = originator_sn;
1001 			path->exp_time = rtw_time_after(path->exp_time, exp_time)
1002 					  ?  path->exp_time : exp_time;
1003 			rtw_mesh_path_activate(path);
1004 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
1005 			if (path->is_root && (action == RTW_MPATH_PREP)) {
1006 				_rtw_memcpy(path->rann_snd_addr,
1007 				mgmt->addr2, ETH_ALEN);
1008 				path->rann_metric = new_metric;
1009 			}
1010 #endif
1011 			exit_critical_bh(&path->state_lock);
1012 			rtw_mesh_path_tx_pending(path);
1013 		} else
1014 			exit_critical_bh(&path->state_lock);
1015 	}
1016 
1017 	/* Update and check transmitter routing info */
1018 	ta = mgmt->addr2;
1019 	if (rtw_ether_addr_equal(originator_addr, ta))
1020 		fresh_info = _FALSE;
1021 	else {
1022 		fresh_info = _TRUE;
1023 
1024 		path = rtw_mesh_path_lookup(adapter, ta);
1025 		if (path) {
1026 			enter_critical_bh(&path->state_lock);
1027 			if ((path->flags & RTW_MESH_PATH_FIXED) ||
1028 				((path->flags & RTW_MESH_PATH_ACTIVE) &&
1029 					(last_hop_metric > path->metric)))
1030 				fresh_info = _FALSE;
1031 		} else {
1032 			path = rtw_mesh_path_add(adapter, ta);
1033 			if (IS_ERR(path)) {
1034 				rtw_rcu_read_unlock();
1035 				return 0;
1036 			}
1037 			enter_critical_bh(&path->state_lock);
1038 		}
1039 
1040 		if (fresh_info) {
1041 			rtw_mesh_path_assign_nexthop(path, sta);
1042 			path->metric = last_hop_metric;
1043 			path->exp_time = rtw_time_after(path->exp_time, exp_time)
1044 					  ?  path->exp_time : exp_time;
1045 			rtw_mesh_path_activate(path);
1046 			exit_critical_bh(&path->state_lock);
1047 			rtw_mesh_path_tx_pending(path);
1048 		} else
1049 			exit_critical_bh(&path->state_lock);
1050 	}
1051 
1052 	rtw_rcu_read_unlock();
1053 
1054 	return process ? new_metric : 0;
1055 }
1056 
rtw_mesh_rx_hwmp_frame_cnts(_adapter * adapter,u8 * addr)1057 static void rtw_mesh_rx_hwmp_frame_cnts(_adapter *adapter, u8 *addr)
1058 {
1059 	struct sta_info *sta;
1060 
1061 	sta = rtw_get_stainfo(&adapter->stapriv, addr);
1062 	if (sta)
1063 		sta->sta_stats.rx_hwmp_pkts++;
1064 }
1065 
rtw_mesh_rx_path_sel_frame(_adapter * adapter,union recv_frame * rframe)1066 void rtw_mesh_rx_path_sel_frame(_adapter *adapter, union recv_frame *rframe)
1067 {
1068 	struct mesh_plink_ent *plink = NULL;
1069 	struct rtw_ieee802_11_elems elems;
1070 	u32 path_metric;
1071 	struct rx_pkt_attrib *attrib = &rframe->u.hdr.attrib;
1072 	u8 *pframe = rframe->u.hdr.rx_data, *start;
1073 	uint frame_len = rframe->u.hdr.len, left;
1074 	struct rtw_ieee80211_hdr_3addr *frame_hdr = (struct rtw_ieee80211_hdr_3addr *)pframe;
1075 	u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1076 	ParseRes parse_res;
1077 
1078 	plink = rtw_mesh_plink_get(adapter, get_addr2_ptr(pframe));
1079 	if (!plink || plink->plink_state != RTW_MESH_PLINK_ESTAB)
1080 		return;
1081 
1082 	rtw_mesh_rx_hwmp_frame_cnts(adapter, get_addr2_ptr(pframe));
1083 
1084 	/* Mesh action frame IE offset = 2 */
1085 	attrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1086 	left = frame_len - attrib->hdrlen - attrib->iv_len - attrib->icv_len - 2;
1087 	start = pframe + attrib->hdrlen + 2;
1088 
1089 	parse_res = rtw_ieee802_11_parse_elems(start, left, &elems, 1);
1090 	if (parse_res == ParseFailed)
1091 		RTW_HWMP_INFO(FUNC_ADPT_FMT" Path Select Frame ParseFailed\n"
1092 			, FUNC_ADPT_ARG(adapter));
1093 	else if (parse_res == ParseUnknown)
1094 		RTW_HWMP_INFO(FUNC_ADPT_FMT" Path Select Frame ParseUnknown\n"
1095 			, FUNC_ADPT_ARG(adapter));
1096 
1097 	if (elems.preq) {
1098 		if (elems.preq_len != 37)
1099 			/* Right now we support just 1 destination and no AE */
1100 			return;
1101 		path_metric = rtw_hwmp_route_info_get(adapter, frame_hdr, elems.preq,
1102 						  MPATH_PREQ);
1103 		if (path_metric)
1104 			rtw_hwmp_preq_frame_process(adapter, frame_hdr, elems.preq,
1105 						path_metric);
1106 	}
1107 	if (elems.prep) {
1108 		if (elems.prep_len != 31)
1109 			/* Right now we support no AE */
1110 			return;
1111 		path_metric = rtw_hwmp_route_info_get(adapter, frame_hdr, elems.prep,
1112 						  MPATH_PREP);
1113 		if (path_metric)
1114 			rtw_hwmp_prep_frame_process(adapter, frame_hdr, elems.prep,
1115 						path_metric);
1116 	}
1117 	if (elems.perr) {
1118 		if (elems.perr_len != 15)
1119 			/* Right now we support only one destination per PERR */
1120 			return;
1121 		rtw_hwmp_perr_frame_process(adapter, frame_hdr, elems.perr);
1122 	}
1123 	if (elems.rann)
1124 		rtw_hwmp_rann_frame_process(adapter, frame_hdr, (struct rtw_ieee80211_rann_ie *)elems.rann);
1125 }
1126 
rtw_mesh_queue_preq(struct rtw_mesh_path * path,u8 flags)1127 void rtw_mesh_queue_preq(struct rtw_mesh_path *path, u8 flags)
1128 {
1129 	_adapter *adapter = path->adapter;
1130 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
1131 	struct rtw_mesh_preq_queue *preq_node;
1132 
1133 	preq_node = rtw_malloc(sizeof(struct rtw_mesh_preq_queue));
1134 	if (!preq_node) {
1135 		RTW_HWMP_INFO("could not allocate PREQ node\n");
1136 		return;
1137 	}
1138 
1139 	enter_critical_bh(&minfo->mesh_preq_queue_lock);
1140 	if (minfo->preq_queue_len == RTW_MAX_PREQ_QUEUE_LEN) {
1141 		exit_critical_bh(&minfo->mesh_preq_queue_lock);
1142 		rtw_mfree(preq_node, sizeof(struct rtw_mesh_preq_queue));
1143 		if (rtw_print_ratelimit())
1144 			RTW_HWMP_INFO("PREQ node queue full\n");
1145 		return;
1146 	}
1147 
1148 	_rtw_spinlock(&path->state_lock);
1149 	if (path->flags & RTW_MESH_PATH_REQ_QUEUED) {
1150 		_rtw_spinunlock(&path->state_lock);
1151 		exit_critical_bh(&minfo->mesh_preq_queue_lock);
1152 		rtw_mfree(preq_node, sizeof(struct rtw_mesh_preq_queue));
1153 		return;
1154 	}
1155 
1156 	_rtw_memcpy(preq_node->dst, path->dst, ETH_ALEN);
1157 	preq_node->flags = flags;
1158 
1159 	path->flags |= RTW_MESH_PATH_REQ_QUEUED;
1160 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
1161 	if (flags & RTW_PREQ_Q_F_CHK)
1162 		path->flags |= RTW_MESH_PATH_ROOT_ADD_CHK;
1163 #endif
1164 	if (flags & RTW_PREQ_Q_F_PEER_AKA)
1165 		path->flags |= RTW_MESH_PATH_PEER_AKA;
1166 	if (flags & RTW_PREQ_Q_F_BCAST_PREQ)
1167 		path->flags |= RTW_MESH_PATH_BCAST_PREQ;
1168 	_rtw_spinunlock(&path->state_lock);
1169 
1170 	rtw_list_insert_tail(&preq_node->list, &minfo->preq_queue.list);
1171 	++minfo->preq_queue_len;
1172 	exit_critical_bh(&minfo->mesh_preq_queue_lock);
1173 
1174 	if (rtw_time_after(rtw_get_current_time(), minfo->last_preq + rtw_min_preq_int_jiff(adapter)))
1175 		rtw_mesh_work(&adapter->mesh_work);
1176 
1177 	else if (rtw_time_before(rtw_get_current_time(), minfo->last_preq)) {
1178 		/* systime wrapped around issue */
1179 		minfo->last_preq = rtw_get_current_time() - rtw_min_preq_int_jiff(adapter) - 1;
1180 		rtw_mesh_work(&adapter->mesh_work);
1181 	} else
1182 		rtw_mod_timer(&adapter->mesh_path_timer, minfo->last_preq +
1183 					rtw_min_preq_int_jiff(adapter) + 1);
1184 }
1185 
rtw_hwmp_preq_da(struct rtw_mesh_path * path,BOOLEAN is_root_add_chk,BOOLEAN da_is_peer,BOOLEAN force_preq_bcast)1186 static const u8 *rtw_hwmp_preq_da(struct rtw_mesh_path *path,
1187 			    BOOLEAN is_root_add_chk, BOOLEAN da_is_peer,
1188 			    BOOLEAN force_preq_bcast)
1189 {
1190 	const u8 *da;
1191 
1192 	if (da_is_peer)
1193 		da = path->dst;
1194 	else if (force_preq_bcast)
1195 		da = bcast_addr;
1196 	else if (path->is_root)
1197 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
1198 		da = is_root_add_chk ? path->add_chk_rann_snd_addr:
1199 				       path->rann_snd_addr;
1200 #else
1201 		da = path->rann_snd_addr;
1202 #endif
1203 	else
1204 		da = bcast_addr;
1205 
1206 	return da;
1207 }
1208 
rtw_mesh_path_start_discovery(_adapter * adapter)1209 void rtw_mesh_path_start_discovery(_adapter *adapter)
1210 {
1211 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
1212 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
1213 	struct rtw_mesh_preq_queue *preq_node;
1214 	struct rtw_mesh_path *path;
1215 	u8 ttl, target_flags = 0;
1216 	const u8 *da;
1217 	u32 lifetime;
1218 	u8 flags = 0;
1219 	BOOLEAN is_root_add_chk = _FALSE;
1220 	BOOLEAN da_is_peer, force_preq_bcast;
1221 
1222 	enter_critical_bh(&minfo->mesh_preq_queue_lock);
1223 	if (!minfo->preq_queue_len ||
1224 		rtw_time_before(rtw_get_current_time(), minfo->last_preq +
1225 				rtw_min_preq_int_jiff(adapter))) {
1226 		exit_critical_bh(&minfo->mesh_preq_queue_lock);
1227 		return;
1228 	}
1229 
1230 	preq_node = rtw_list_first_entry(&minfo->preq_queue.list,
1231 			struct rtw_mesh_preq_queue, list);
1232 	rtw_list_delete(&preq_node->list); /* list_del_init(&preq_node->list); */
1233 	--minfo->preq_queue_len;
1234 	exit_critical_bh(&minfo->mesh_preq_queue_lock);
1235 
1236 	rtw_rcu_read_lock();
1237 	path = rtw_mesh_path_lookup(adapter, preq_node->dst);
1238 	if (!path)
1239 		goto enddiscovery;
1240 
1241 	enter_critical_bh(&path->state_lock);
1242 	if (path->flags & (RTW_MESH_PATH_DELETED | RTW_MESH_PATH_FIXED)) {
1243 		exit_critical_bh(&path->state_lock);
1244 		goto enddiscovery;
1245 	}
1246 	path->flags &= ~RTW_MESH_PATH_REQ_QUEUED;
1247 	if (preq_node->flags & RTW_PREQ_Q_F_START) {
1248 		if (path->flags & RTW_MESH_PATH_RESOLVING) {
1249 			exit_critical_bh(&path->state_lock);
1250 			goto enddiscovery;
1251 		} else {
1252 			path->flags &= ~RTW_MESH_PATH_RESOLVED;
1253 			path->flags |= RTW_MESH_PATH_RESOLVING;
1254 			path->discovery_retries = 0;
1255 			path->discovery_timeout = rtw_disc_timeout_jiff(adapter);
1256 		}
1257 	} else if (!(path->flags & RTW_MESH_PATH_RESOLVING) ||
1258 			path->flags & RTW_MESH_PATH_RESOLVED) {
1259 		path->flags &= ~RTW_MESH_PATH_RESOLVING;
1260 		exit_critical_bh(&path->state_lock);
1261 		goto enddiscovery;
1262 	}
1263 
1264 	minfo->last_preq = rtw_get_current_time();
1265 
1266 	if (rtw_time_after(rtw_get_current_time(), minfo->last_sn_update +
1267 				rtw_net_traversal_jiffies(adapter)) ||
1268 	    rtw_time_before(rtw_get_current_time(), minfo->last_sn_update)) {
1269 		++minfo->sn;
1270 		minfo->last_sn_update = rtw_get_current_time();
1271 	}
1272 	lifetime = rtw_default_lifetime(adapter);
1273 	ttl = mshcfg->element_ttl;
1274 	if (ttl == 0) {
1275 		minfo->mshstats.dropped_frames_ttl++;
1276 		exit_critical_bh(&path->state_lock);
1277 		goto enddiscovery;
1278 	}
1279 
1280 	if (preq_node->flags & RTW_PREQ_Q_F_REFRESH)
1281 		target_flags |= RTW_IEEE80211_PREQ_TO_FLAG;
1282 	else
1283 		target_flags &= ~RTW_IEEE80211_PREQ_TO_FLAG;
1284 
1285 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
1286 	is_root_add_chk = !!(path->flags & RTW_MESH_PATH_ROOT_ADD_CHK);
1287 #endif
1288 	da_is_peer = !!(path->flags & RTW_MESH_PATH_PEER_AKA);
1289 	force_preq_bcast = !!(path->flags & RTW_MESH_PATH_BCAST_PREQ);
1290 	exit_critical_bh(&path->state_lock);
1291 
1292 	da = rtw_hwmp_preq_da(path, is_root_add_chk,
1293 			      da_is_peer, force_preq_bcast);
1294 
1295 #ifdef CONFIG_RTW_MESH_ON_DMD_GANN
1296 	flags = (mshcfg->dot11MeshGateAnnouncementProtocol)
1297 		? RTW_IEEE80211_PREQ_IS_GATE_FLAG : 0;
1298 #endif
1299 	rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREQ, flags, adapter_mac_addr(adapter), minfo->sn,
1300 				   target_flags, path->dst, path->sn, da, 0,
1301 				   ttl, lifetime, 0, minfo->preq_id++, adapter);
1302 	rtw_mod_timer(&path->timer, rtw_get_current_time() + path->discovery_timeout);
1303 
1304 enddiscovery:
1305 	rtw_rcu_read_unlock();
1306 	rtw_mfree(preq_node, sizeof(struct rtw_mesh_preq_queue));
1307 }
1308 
rtw_mesh_path_timer(void * ctx)1309 void rtw_mesh_path_timer(void *ctx)
1310 {
1311 	struct rtw_mesh_path *path = (void *) ctx;
1312 	_adapter *adapter = path->adapter;
1313 	int ret;
1314 	u8 retry = 0;
1315 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
1316 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
1317 #endif
1318 	/* TBD: Proctect for suspend */
1319 #if 0
1320 	if (suspending)
1321 		return;
1322 #endif
1323 	enter_critical_bh(&path->state_lock);
1324 	if (path->flags & RTW_MESH_PATH_RESOLVED ||
1325 			(!(path->flags & RTW_MESH_PATH_RESOLVING))) {
1326 		path->flags &= ~(RTW_MESH_PATH_RESOLVING |
1327 				 RTW_MESH_PATH_RESOLVED |
1328 				 RTW_MESH_PATH_ROOT_ADD_CHK |
1329 				 RTW_MESH_PATH_PEER_AKA |
1330 				 RTW_MESH_PATH_BCAST_PREQ);
1331 		exit_critical_bh(&path->state_lock);
1332 	} else if (path->discovery_retries < rtw_max_preq_retries(adapter)) {
1333 		++path->discovery_retries;
1334 		path->discovery_timeout *= 2;
1335 		path->flags &= ~RTW_MESH_PATH_REQ_QUEUED;
1336 #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK
1337 		if (path->discovery_retries > mshcfg->max_root_add_chk_cnt)
1338 			path->flags &= ~RTW_MESH_PATH_ROOT_ADD_CHK;
1339 #endif
1340 		if (path->gate_asked)
1341 			retry |= RTW_PREQ_Q_F_REFRESH;
1342 
1343 		exit_critical_bh(&path->state_lock);
1344 		rtw_mesh_queue_preq(path, retry);
1345 	} else {
1346 		path->flags &= ~(RTW_MESH_PATH_RESOLVING |
1347 				  RTW_MESH_PATH_RESOLVED |
1348 				  RTW_MESH_PATH_REQ_QUEUED |
1349 				  RTW_MESH_PATH_ROOT_ADD_CHK |
1350 				  RTW_MESH_PATH_PEER_AKA |
1351 				  RTW_MESH_PATH_BCAST_PREQ);
1352 		path->exp_time = rtw_get_current_time();
1353 		exit_critical_bh(&path->state_lock);
1354 		if (!path->is_gate && rtw_mesh_gate_num(adapter) > 0) {
1355 			ret = rtw_mesh_path_send_to_gates(path);
1356 			if (ret)
1357 				RTW_HWMP_DBG("no gate was reachable\n");
1358 		} else
1359 			rtw_mesh_path_flush_pending(path);
1360 	}
1361 }
1362 
1363 
rtw_mesh_path_tx_root_frame(_adapter * adapter)1364 void rtw_mesh_path_tx_root_frame(_adapter *adapter)
1365 {
1366 	struct rtw_mesh_cfg *mshcfg = &adapter->mesh_cfg;
1367 	struct rtw_mesh_info *minfo = &adapter->mesh_info;
1368 	u32 interval = mshcfg->dot11MeshHWMPRannInterval;
1369 	u8 flags, target_flags = 0;
1370 
1371 	flags = (mshcfg->dot11MeshGateAnnouncementProtocol)
1372 			? RTW_RANN_FLAG_IS_GATE : 0;
1373 
1374 	switch (mshcfg->dot11MeshHWMPRootMode) {
1375 	case RTW_IEEE80211_PROACTIVE_RANN:
1376 		rtw_mesh_path_sel_frame_tx(RTW_MPATH_RANN, flags, adapter_mac_addr(adapter),
1377 					   ++minfo->sn, 0, NULL, 0, bcast_addr,
1378 					   0, mshcfg->element_ttl,
1379 					   interval, 0, 0, adapter);
1380 		break;
1381 	case RTW_IEEE80211_PROACTIVE_PREQ_WITH_PREP:
1382 		flags |= RTW_IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
1383 	case RTW_IEEE80211_PROACTIVE_PREQ_NO_PREP:
1384 		interval = mshcfg->dot11MeshHWMPactivePathToRootTimeout;
1385 		target_flags |= RTW_IEEE80211_PREQ_TO_FLAG |
1386 				RTW_IEEE80211_PREQ_USN_FLAG;
1387 		rtw_mesh_path_sel_frame_tx(RTW_MPATH_PREQ, flags, adapter_mac_addr(adapter),
1388 					   ++minfo->sn, target_flags,
1389 					   (u8 *) bcast_addr, 0, bcast_addr,
1390 					   0, mshcfg->element_ttl, interval,
1391 					   0, minfo->preq_id++, adapter);
1392 		break;
1393 	default:
1394 		RTW_HWMP_INFO("Proactive mechanism not supported\n");
1395 		return;
1396 	}
1397 }
1398 
rtw_mesh_work(_workitem * work)1399 void rtw_mesh_work(_workitem *work)
1400 {
1401 	/* use kernel global workqueue */
1402 	_set_workitem(work);
1403 }
1404 
rtw_ieee80211_mesh_path_timer(void * ctx)1405 void rtw_ieee80211_mesh_path_timer(void *ctx)
1406 {
1407 	_adapter *adapter = (_adapter *)ctx;
1408 	rtw_mesh_work(&adapter->mesh_work);
1409 }
1410 
rtw_ieee80211_mesh_path_root_timer(void * ctx)1411 void rtw_ieee80211_mesh_path_root_timer(void *ctx)
1412 {
1413 	_adapter *adapter = (_adapter *)ctx;
1414 
1415 	rtw_set_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags);
1416 
1417 	rtw_mesh_work(&adapter->mesh_work);
1418 }
1419 
rtw_ieee80211_mesh_rootpath(_adapter * adapter)1420 static void rtw_ieee80211_mesh_rootpath(_adapter *adapter)
1421 {
1422 	u32 interval;
1423 
1424 	rtw_mesh_path_tx_root_frame(adapter);
1425 
1426 	if (adapter->mesh_cfg.dot11MeshHWMPRootMode == RTW_IEEE80211_PROACTIVE_RANN)
1427 		interval = adapter->mesh_cfg.dot11MeshHWMPRannInterval;
1428 	else
1429 		interval = adapter->mesh_cfg.dot11MeshHWMProotInterval;
1430 
1431 	rtw_mod_timer(&adapter->mesh_path_root_timer,
1432 		  RTW_TU_TO_EXP_TIME(interval));
1433 }
1434 
rtw_ieee80211_mesh_root_setup(_adapter * adapter)1435 BOOLEAN rtw_ieee80211_mesh_root_setup(_adapter *adapter)
1436 {
1437 	BOOLEAN root_enabled = _FALSE;
1438 
1439 	if (adapter->mesh_cfg.dot11MeshHWMPRootMode > RTW_IEEE80211_ROOTMODE_ROOT) {
1440 		rtw_set_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags);
1441 		root_enabled = _TRUE;
1442 	}
1443 	else {
1444 		rtw_clear_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags);
1445 		/* stop running timer */
1446 		_cancel_timer_ex(&adapter->mesh_path_root_timer);
1447 		root_enabled = _FALSE;
1448 	}
1449 
1450 	return root_enabled;
1451 }
1452 
rtw_mesh_work_hdl(_workitem * work)1453 void rtw_mesh_work_hdl(_workitem *work)
1454 {
1455 	_adapter *adapter = container_of(work, _adapter, mesh_work);
1456 
1457 	while(adapter->mesh_info.preq_queue_len) {
1458 		if (rtw_time_after(rtw_get_current_time(),
1459 		       adapter->mesh_info.last_preq + rtw_min_preq_int_jiff(adapter)))
1460 		       /* It will consume preq_queue_len */
1461 		       rtw_mesh_path_start_discovery(adapter);
1462 		else {
1463 			struct rtw_mesh_info *minfo = &adapter->mesh_info;
1464 
1465 			rtw_mod_timer(&adapter->mesh_path_timer,
1466 				minfo->last_preq + rtw_min_preq_int_jiff(adapter) + 1);
1467 			break;
1468 		}
1469 	}
1470 
1471 	if (rtw_test_and_clear_bit(RTW_MESH_WORK_ROOT, &adapter->wrkq_flags))
1472 		rtw_ieee80211_mesh_rootpath(adapter);
1473 }
1474 
1475 #ifndef RTW_PER_CMD_SUPPORT_FW
rtw_update_metric_directly(_adapter * adapter)1476 static void rtw_update_metric_directly(_adapter *adapter)
1477 {
1478 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1479 	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
1480 	u8 i;
1481 
1482 	for (i = 0; i < macid_ctl->num; i++) {
1483 		u8 role;
1484 		role = GET_H2CCMD_MSRRPT_PARM_ROLE(&macid_ctl->h2c_msr[i]);
1485 		if (role == H2C_MSR_ROLE_MESH) {
1486 			struct sta_info *sta = macid_ctl->sta[i];
1487 			u8 rate_idx, sgi, bw;
1488 			u32 rate;
1489 
1490 			if (!sta)
1491 				continue;
1492 			rate_idx = rtw_get_current_tx_rate(adapter, sta);
1493 			sgi = rtw_get_current_tx_sgi(adapter, sta);
1494 			bw = sta->cmn.bw_mode;
1495 			rate = rtw_desc_rate_to_bitrate(bw, rate_idx, sgi);
1496 			sta->metrics.data_rate = rate;
1497 		}
1498 	}
1499 }
1500 #endif
1501 
rtw_mesh_atlm_param_req_timer(void * ctx)1502 void rtw_mesh_atlm_param_req_timer(void *ctx)
1503 {
1504 	_adapter *adapter = (_adapter *)ctx;
1505 	u8 ret = _FAIL;
1506 
1507 #ifdef RTW_PER_CMD_SUPPORT_FW
1508 	ret = rtw_req_per_cmd(adapter);
1509 	if (ret == _FAIL)
1510 		RTW_HWMP_INFO("rtw_req_per_cmd fail\n");
1511 #else
1512 	rtw_update_metric_directly(adapter);
1513 #endif
1514 	_set_timer(&adapter->mesh_atlm_param_req_timer, RTW_ATLM_REQ_CYCLE);
1515 }
1516 
1517 #endif /* CONFIG_RTW_MESH */
1518 
1519