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