qca_multi_link.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243
  1. /*
  2. * Copyright (c) 2020 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "qca_multi_link.h"
  17. static bool is_initialized;
  18. qca_multi_link_parameters_t qca_multi_link_cfg;
  19. static inline bool is_fast_lane_radio(struct wiphy *fl_wiphy)
  20. {
  21. qdf_list_node_t *node = NULL, *next_node = NULL;
  22. if (!fl_wiphy) {
  23. return false;
  24. }
  25. if (qdf_list_empty(&qca_multi_link_cfg.fast_lane_list)) {
  26. return false;
  27. }
  28. qdf_list_peek_front(&qca_multi_link_cfg.fast_lane_list,
  29. (qdf_list_node_t **)&next_node);
  30. while (next_node) {
  31. struct qca_multi_link_list_node *fast_lane_node
  32. = (struct qca_multi_link_list_node *)next_node;
  33. if (fast_lane_node->wiphy == fl_wiphy) {
  34. return true;
  35. } else {
  36. node = next_node;
  37. next_node = NULL;
  38. if ((qdf_list_peek_next(&qca_multi_link_cfg.fast_lane_list, node, &next_node))
  39. != QDF_STATUS_SUCCESS) {
  40. return false;
  41. }
  42. }
  43. }
  44. return false;
  45. }
  46. static inline bool is_no_backhaul_radio(struct wiphy *no_bl_wiphy)
  47. {
  48. qdf_list_node_t *node = NULL, *next_node = NULL;
  49. if (!no_bl_wiphy) {
  50. return false;
  51. }
  52. if (qdf_list_empty(&qca_multi_link_cfg.no_backhaul_list)) {
  53. return false;
  54. }
  55. qdf_list_peek_front(&qca_multi_link_cfg.no_backhaul_list,
  56. (qdf_list_node_t **)&next_node);
  57. while (next_node) {
  58. struct qca_multi_link_list_node *no_bl_node
  59. = (struct qca_multi_link_list_node *)next_node;
  60. if (no_bl_node->wiphy == no_bl_wiphy) {
  61. return true;
  62. } else {
  63. node = next_node;
  64. next_node = NULL;
  65. if ((qdf_list_peek_next(&qca_multi_link_cfg.no_backhaul_list, node, &next_node))
  66. != QDF_STATUS_SUCCESS) {
  67. return false;
  68. }
  69. }
  70. }
  71. return false;
  72. }
  73. static inline bool is_other_fast_lane_radio_primary(struct wiphy *fl_wiphy)
  74. {
  75. qdf_list_node_t *next_node = NULL;
  76. if (!fl_wiphy) {
  77. return false;
  78. }
  79. if (qdf_list_empty(&qca_multi_link_cfg.fast_lane_list)) {
  80. return false;
  81. }
  82. qdf_list_peek_front(&qca_multi_link_cfg.fast_lane_list,
  83. (qdf_list_node_t **)&next_node);
  84. while (next_node) {
  85. struct qca_multi_link_list_node *fast_lane_node
  86. = (struct qca_multi_link_list_node *)next_node;
  87. if ((fast_lane_node->wiphy != fl_wiphy)
  88. && (fast_lane_node->wiphy == qca_multi_link_cfg.primary_wiphy)) {
  89. return true;
  90. }
  91. }
  92. return false;
  93. }
  94. /**
  95. * qca_multi_link_is_primary_radio() - Check if this is a primary radio
  96. *
  97. * Return: true: if it primary radio
  98. * false: if it is secondary radio
  99. */
  100. static inline bool qca_multi_link_is_primary_radio(struct wiphy *dev_wiphy)
  101. {
  102. bool is_primary = false;
  103. if (!qca_multi_link_cfg.primary_wiphy || !dev_wiphy) {
  104. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  105. FL("\nprimary_wiphy is NULL\n"));
  106. is_primary = false;
  107. } else {
  108. is_primary = (dev_wiphy == qca_multi_link_cfg.primary_wiphy)?true:false;
  109. }
  110. if ((is_primary == false) && is_fast_lane_radio(dev_wiphy)) {
  111. is_primary = is_other_fast_lane_radio_primary(dev_wiphy);
  112. }
  113. return is_primary;
  114. }
  115. /**
  116. * qca_multi_link_need_procesing() - Check if repeater processing is required
  117. *
  118. * Return: true: processing is required
  119. * false: processing is not required
  120. */
  121. static inline bool qca_multi_link_need_procesing(void)
  122. {
  123. if ((!qca_multi_link_cfg.rptr_processing_enable)
  124. || (qca_multi_link_cfg.total_stavaps_up < 2)) {
  125. return false;
  126. }
  127. return true;
  128. }
  129. /**
  130. * qca_multi_link_pktfrom_ownsrc() - Check if packet is from same device
  131. *
  132. * Return: true: packet is from same device
  133. * false: packet is not from same device
  134. */
  135. static inline bool qca_multi_link_pktfrom_ownsrc(struct net_device *net_dev, qdf_nbuf_t nbuf)
  136. {
  137. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  138. if (qdf_is_macaddr_equal((struct qdf_mac_addr *)net_dev->dev_addr,
  139. (struct qdf_mac_addr *)eh->ether_shost)) {
  140. return true;
  141. }
  142. return false;
  143. }
  144. /**
  145. * qca_multi_link_drop_secondary_mcast() - Check if mcast to be dropped on secondary
  146. *
  147. * Return: true: Drop the packet
  148. * false: Do not drop
  149. */
  150. static inline bool qca_multi_link_drop_secondary_mcast(qdf_nbuf_t nbuf)
  151. {
  152. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  153. uint8_t is_mcast = IEEE80211_IS_MULTICAST(eh->ether_dhost);
  154. if (is_mcast && qca_multi_link_cfg.drop_secondary_mcast) {
  155. return true;
  156. }
  157. return false;
  158. }
  159. /**
  160. * qca_multi_link_drop_always_primary() - Check if packet to be dropped for always_primary
  161. *
  162. * Return: true: Drop the packet
  163. * false: Do not drop
  164. */
  165. static inline bool qca_multi_link_drop_always_primary(bool is_primary, qdf_nbuf_t nbuf)
  166. {
  167. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  168. if (qca_multi_link_cfg.always_primary) {
  169. if (is_primary) {
  170. return false;
  171. } else {
  172. if (eh->ether_type != qdf_htons(ETHERTYPE_PAE)) {
  173. return true;
  174. }
  175. }
  176. }
  177. return false;
  178. }
  179. /**
  180. * qca_multi_link_deinit_module() - De-initialize the repeater base structute
  181. * Return: void
  182. */
  183. void qca_multi_link_deinit_module(void)
  184. {
  185. if (!is_initialized)
  186. return;
  187. qca_multi_link_cfg.total_stavaps_up = 0;
  188. qca_multi_link_cfg.loop_detected = 0;
  189. qca_multi_link_cfg.primary_wiphy = NULL;
  190. qdf_list_destroy(&qca_multi_link_cfg.fast_lane_list);
  191. qdf_list_destroy(&qca_multi_link_cfg.no_backhaul_list);
  192. is_initialized = false;
  193. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
  194. FL("\n******QCA RPtr De-Init Done***********\n"));
  195. }
  196. qdf_export_symbol(qca_multi_link_deinit_module);
  197. /**
  198. * qca_multi_link_init_module() - Initialize the repeater base structute
  199. *
  200. * Return: void
  201. */
  202. void qca_multi_link_init_module(void)
  203. {
  204. if (is_initialized)
  205. return;
  206. is_initialized = true;
  207. qca_multi_link_cfg.total_stavaps_up = 0;
  208. qca_multi_link_cfg.loop_detected = 0;
  209. qca_multi_link_cfg.primary_wiphy = NULL;
  210. qdf_list_create(&qca_multi_link_cfg.fast_lane_list, QCA_MULTI_LINK_FAST_LANE_LIST_SIZE);
  211. qdf_list_create(&qca_multi_link_cfg.no_backhaul_list, QCA_MULTI_LINK_NO_BACKHAUL_LIST_SIZE);
  212. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
  213. FL("\n******QCA Repeater Initialization Done***********\n"));
  214. }
  215. qdf_export_symbol(qca_multi_link_init_module);
  216. /**
  217. * qca_multi_link_get_num_sta() - Get the total number of sta vaps up.
  218. *
  219. * Return: int
  220. */
  221. uint8_t qca_multi_link_get_num_sta(void)
  222. {
  223. return qca_multi_link_cfg.total_stavaps_up;
  224. }
  225. qdf_export_symbol(qca_multi_link_get_num_sta);
  226. /**
  227. * qca_multi_link_append_num_sta() - Append the total number of sta vaps up.
  228. * @inc_or_dec: true to increment and false to decrement
  229. *
  230. * Return: void
  231. */
  232. void qca_multi_link_append_num_sta(bool inc_or_dec)
  233. {
  234. if (inc_or_dec) {
  235. qca_multi_link_cfg.total_stavaps_up++;
  236. if (qca_multi_link_cfg.total_stavaps_up > 1) {
  237. qca_multi_link_set_drop_sec_mcast(true);
  238. }
  239. } else {
  240. if (qca_multi_link_cfg.total_stavaps_up == 0) {
  241. return;
  242. }
  243. qca_multi_link_cfg.total_stavaps_up--;
  244. if (qca_multi_link_cfg.total_stavaps_up <= 1) {
  245. qca_multi_link_cfg.loop_detected = 0;
  246. }
  247. }
  248. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_NONE,
  249. FL("\nStation vap number in Repeater is val=%d***********\n"),
  250. qca_multi_link_cfg.total_stavaps_up);
  251. }
  252. qdf_export_symbol(qca_multi_link_append_num_sta);
  253. /**
  254. * qca_multi_link_is_dbdc_processing_reqd() - Check if dbdc processing is required
  255. * @net_dev: current net device
  256. *
  257. * Return: true: loop is detected
  258. * false: loop not detected
  259. */
  260. bool qca_multi_link_is_dbdc_processing_reqd(struct net_device *net_dev)
  261. {
  262. if (qca_multi_link_cfg.total_stavaps_up > 2)
  263. return (qca_multi_link_cfg.loop_detected && qca_multi_link_cfg.rptr_processing_enable);
  264. else
  265. return false;
  266. }
  267. qdf_export_symbol(qca_multi_link_is_dbdc_processing_reqd);
  268. /**
  269. * qca_multi_link_set_drop_sec_mcast() - set the drop secondary mcast flag
  270. * @val: boolean true or false
  271. *
  272. */
  273. void qca_multi_link_set_drop_sec_mcast(bool val)
  274. {
  275. qca_multi_link_cfg.drop_secondary_mcast = val;
  276. }
  277. qdf_export_symbol(qca_multi_link_set_drop_sec_mcast);
  278. /**
  279. * qca_multi_link_set_force_client_mcast() - set the flag to force client mcast traffic
  280. * @val: boolean true or false
  281. *
  282. */
  283. void qca_multi_link_set_force_client_mcast(bool val)
  284. {
  285. qca_multi_link_cfg.force_client_mcast_traffic = val;
  286. }
  287. qdf_export_symbol(qca_multi_link_set_force_client_mcast);
  288. /**
  289. * qca_multi_link_set_always_primary() - set the flag for always primary flag
  290. * @val: boolean true or false
  291. *
  292. */
  293. void qca_multi_link_set_always_primary(bool val)
  294. {
  295. qca_multi_link_cfg.always_primary = val;
  296. }
  297. qdf_export_symbol(qca_multi_link_set_always_primary);
  298. /**
  299. * qca_multi_link_set_dbdc_enable() - set the dbdc enable flag
  300. * @val: boolean true or false
  301. */
  302. void qca_multi_link_set_dbdc_enable(bool val)
  303. {
  304. qca_multi_link_cfg.rptr_processing_enable = val;
  305. if (!val) {
  306. qca_multi_link_cfg.loop_detected = 0;
  307. }
  308. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  309. FL("\nSetting DBDC enable = val%d\n"), val);
  310. }
  311. qdf_export_symbol(qca_multi_link_set_dbdc_enable);
  312. /**
  313. * qca_multi_link_get_primary_radio() - set the dbdc enable flag
  314. * @primary_wiphy: wiphy pointer of primary radio device
  315. */
  316. struct wiphy *qca_multi_link_get_primary_radio(void)
  317. {
  318. return qca_multi_link_cfg.primary_wiphy;
  319. }
  320. qdf_export_symbol(qca_multi_link_get_primary_radio);
  321. /**
  322. * qca_multi_link_set_primary_radio() - set the primary radio
  323. * @primary_wiphy: wiphy pointer of primary radio device
  324. */
  325. void qca_multi_link_set_primary_radio(struct wiphy *primary_wiphy)
  326. {
  327. if (!primary_wiphy) {
  328. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  329. FL("\nNull wiphy in Setting primary radio\n"));
  330. return;
  331. }
  332. qca_multi_link_cfg.primary_wiphy = primary_wiphy;
  333. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
  334. FL("\nSetting primary radio for wiphy%p\n"), primary_wiphy);
  335. }
  336. qdf_export_symbol(qca_multi_link_set_primary_radio);
  337. /**
  338. * qca_multi_link_add_fastlane_radio() - add the fast lane radio pointer to list
  339. * @primary_wiphy: wiphy pointer of fast-lane radio device
  340. *
  341. * Return: false: addition not successful
  342. * true: addition is successful
  343. */
  344. bool qca_multi_link_add_fastlane_radio(struct wiphy *fl_wiphy)
  345. {
  346. struct qca_multi_link_list_node *fast_lane_node;
  347. if (!fl_wiphy) {
  348. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
  349. FL(" Fast lane radio could not be set - wiphy is NULL\n"));
  350. return false;
  351. }
  352. fast_lane_node = qdf_mem_malloc(sizeof(struct qca_multi_link_list_node));
  353. if (!fast_lane_node) {
  354. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  355. FL("Could not allocate fast-lane node for wiphy%p\n"), fl_wiphy);
  356. return false;
  357. }
  358. fast_lane_node->wiphy = fl_wiphy;
  359. if (qdf_list_insert_front(&qca_multi_link_cfg.fast_lane_list, &fast_lane_node->node)
  360. == QDF_STATUS_SUCCESS) {
  361. return true;
  362. }
  363. return false;
  364. }
  365. qdf_export_symbol(qca_multi_link_add_fastlane_radio);
  366. /**
  367. * qca_multi_link_remove_fastlane_radio() - remove the fast lane radio pointer from list
  368. * @primary_wiphy: wiphy pointer of fast-lane radio device
  369. *
  370. * Return: false: addition not successful
  371. * true: addition is successful
  372. */
  373. bool qca_multi_link_remove_fastlane_radio(struct wiphy *fl_wiphy)
  374. {
  375. qdf_list_node_t *node = NULL, *next_node = NULL;
  376. if (!fl_wiphy) {
  377. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
  378. FL(" Fast lane radio could not be removed - wiphy is NULL\n"));
  379. return false;
  380. }
  381. qdf_list_peek_front(&qca_multi_link_cfg.fast_lane_list,
  382. (qdf_list_node_t **)&next_node);
  383. while (next_node) {
  384. struct qca_multi_link_list_node *fast_lane_node
  385. = (struct qca_multi_link_list_node *)next_node;
  386. if (fast_lane_node->wiphy == fl_wiphy) {
  387. qdf_list_remove_node(&qca_multi_link_cfg.fast_lane_list, next_node);
  388. qdf_mem_free(fast_lane_node);
  389. return true;
  390. } else {
  391. node = next_node;
  392. next_node = NULL;
  393. if ((qdf_list_peek_next(&qca_multi_link_cfg.fast_lane_list, node,
  394. (qdf_list_node_t **)&next_node)) != QDF_STATUS_SUCCESS) {
  395. return false;
  396. }
  397. }
  398. }
  399. return false;
  400. }
  401. qdf_export_symbol(qca_multi_link_remove_fastlane_radio);
  402. /**
  403. * qca_multi_link_add_no_backhaul_radio() - add the no backhaul radio pointer to list
  404. * @primary_wiphy: wiphy pointer of fast-lane radio device
  405. *
  406. * Return: false: addition not successful
  407. * true: addition is successful
  408. */
  409. bool qca_multi_link_add_no_backhaul_radio(struct wiphy *no_bl_wiphy)
  410. {
  411. struct qca_multi_link_list_node *no_bl_node;
  412. if (!no_bl_wiphy) {
  413. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
  414. FL(" No backhaul radio could not be set - wiphy is NULL\n"));
  415. return false;
  416. }
  417. no_bl_node = qdf_mem_malloc(sizeof(struct qca_multi_link_list_node));
  418. if (!no_bl_node) {
  419. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  420. FL("Could not allocate back-haul node for wiphy%p\n"), no_bl_node);
  421. return false;
  422. }
  423. no_bl_node->wiphy = no_bl_wiphy;
  424. if (qdf_list_insert_front(&qca_multi_link_cfg.no_backhaul_list, &no_bl_node->node)
  425. == QDF_STATUS_SUCCESS) {
  426. return true;
  427. }
  428. return false;
  429. }
  430. qdf_export_symbol(qca_multi_link_add_no_backhaul_radio);
  431. /**
  432. * qca_multi_link_remove_no_backhaul_radio() - remove no-backhaul radio pointer from list
  433. * @primary_wiphy: wiphy pointer of no-backhaul radio device
  434. *
  435. * Return: false: addition not successful
  436. * true: addition is successful
  437. */
  438. bool qca_multi_link_remove_no_backhaul_radio(struct wiphy *no_bl_wiphy)
  439. {
  440. qdf_list_node_t *node = NULL, *next_node = NULL;
  441. if (!no_bl_wiphy) {
  442. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_WARN,
  443. FL(" No backhaul radio could not be removed - wiphy is NULL\n"));
  444. return false;
  445. }
  446. qdf_list_peek_front(&qca_multi_link_cfg.no_backhaul_list,
  447. (qdf_list_node_t **)&next_node);
  448. while (next_node) {
  449. struct qca_multi_link_list_node *no_bl_node
  450. = (struct qca_multi_link_list_node *)next_node;
  451. if (no_bl_node->wiphy == no_bl_wiphy) {
  452. qdf_list_remove_node(&qca_multi_link_cfg.no_backhaul_list, next_node);
  453. qdf_mem_free(no_bl_node);
  454. return true;
  455. } else {
  456. node = next_node;
  457. next_node = NULL;
  458. if ((qdf_list_peek_next(&qca_multi_link_cfg.no_backhaul_list, node, &next_node))
  459. != QDF_STATUS_SUCCESS) {
  460. return false;
  461. }
  462. }
  463. }
  464. return false;
  465. }
  466. qdf_export_symbol(qca_multi_link_remove_no_backhaul_radio);
  467. /**
  468. * qca_multi_link_secondary_ap_rx() - Processing for frames recieved on Secondary AP VAP
  469. * @net_device: net device handle
  470. * @nbuf: frame
  471. *
  472. * Return: qca_multi_link_status_t
  473. * QCA_MULTI_LINK_PKT_ALLOW: frame should be processed further by caller.
  474. * QCA_MULTI_LINK_PKT_DROP: frame to be dropped.
  475. * QCA_MULTI_LINK_PKT_CONSUMED: frame is consumed.
  476. */
  477. static qca_multi_link_status_t qca_multi_link_secondary_ap_rx(struct net_device *ap_dev, qdf_nbuf_t nbuf)
  478. {
  479. struct wiphy *ap_wiphy = NULL;
  480. struct net_device *sta_dev = NULL;
  481. qca_multi_link_tbl_entry_t qca_ml_entry;
  482. QDF_STATUS qal_status = QDF_STATUS_E_FAILURE;
  483. bool enqueue_to_sta_vap = false;
  484. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  485. ap_wiphy = ap_dev->ieee80211_ptr->wiphy;
  486. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("Secondary AP Rx: always_primary=%d, loop_detected=%d,\
  487. drop_secondary_mcast=%d, shost %pM dhost %pM\n"),
  488. qca_multi_link_cfg.always_primary, qca_multi_link_cfg.loop_detected,
  489. qca_multi_link_cfg.drop_secondary_mcast, eh->ether_shost, eh->ether_dhost);
  490. /*
  491. *If the AP is on a fast lane radio, always give the packet to bridge.
  492. */
  493. if (is_fast_lane_radio(ap_wiphy)) {
  494. return QCA_MULTI_LINK_PKT_ALLOW;
  495. }
  496. qca_ml_entry.qal_fdb_ieee80211_ptr = NULL;
  497. qca_ml_entry.qal_fdb_dev = NULL;
  498. qca_ml_entry.qal_fdb_is_local = 0;
  499. qal_status = qca_multi_link_tbl_has_entry(ap_dev, eh->ether_dhost, 0,
  500. &qca_ml_entry);
  501. if (qal_status == QDF_STATUS_SUCCESS) {
  502. /*
  503. * Check the FDB entry type, if the mac-address is learnt on a port which is
  504. * of type station, then it is a source on the RootAP side and enqueue the
  505. * packet to the corresponding station vap. Else give the packet to bridge.
  506. */
  507. if (qca_ml_entry.qal_fdb_ieee80211_ptr
  508. && (qca_ml_entry.qal_fdb_ieee80211_ptr->iftype == NL80211_IFTYPE_STATION)) {
  509. enqueue_to_sta_vap = true;
  510. }
  511. } else {
  512. /*
  513. * If there is no fdb entry, then also the destination might be on the RootAP side,
  514. * enqueue the packet to the corresponding station vap.
  515. */
  516. enqueue_to_sta_vap = true;
  517. }
  518. if (enqueue_to_sta_vap) {
  519. /*
  520. * Find the station vap corresponding to the AP vap.
  521. */
  522. sta_dev = qca_multi_link_tbl_find_sta_or_ap(ap_dev, 1);
  523. if (!sta_dev) {
  524. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  525. FL("Null STA device found %pM - Give to bridge\n"), eh->ether_shost);
  526. return QCA_MULTI_LINK_PKT_DROP;
  527. }
  528. dev_hold(sta_dev);
  529. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  530. FL("shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
  531. /*
  532. * For packets destined to sources on RootAP directly enq to STA vap.
  533. */
  534. sta_dev->netdev_ops->ndo_start_xmit(nbuf, sta_dev);
  535. dev_put(sta_dev);
  536. return QCA_MULTI_LINK_PKT_CONSUMED;
  537. }
  538. return QCA_MULTI_LINK_PKT_ALLOW;
  539. }
  540. /**
  541. * qca_multi_link_ap_rx() - Processing for frames recieved on AP VAP
  542. * @net_device: net device handle
  543. * @nbuf: frame
  544. *
  545. * Return: false: frame not consumed and should be processed further by caller
  546. * true: frame consumed
  547. */
  548. bool qca_multi_link_ap_rx(struct net_device *net_dev, qdf_nbuf_t nbuf)
  549. {
  550. uint8_t is_mcast;
  551. uint8_t is_eapol;
  552. struct net_device *ap_dev = net_dev;
  553. qca_multi_link_status_t status = QCA_MULTI_LINK_PKT_NONE;
  554. struct wiphy *ap_wiphy = NULL;
  555. bool drop_packet = false;
  556. bool is_primary = false;
  557. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  558. if (!qca_multi_link_need_procesing()) {
  559. goto end;
  560. }
  561. if (!qca_multi_link_cfg.loop_detected) {
  562. goto end;
  563. }
  564. /*
  565. * If it is mcast/broadcast frame, AST search cannot be done, so give
  566. * the frame up the stack
  567. * If it is EAPOL frame, just give the frame up the stack
  568. */
  569. is_mcast = IEEE80211_IS_MULTICAST(eh->ether_dhost);
  570. is_eapol = (eh->ether_type == htons(ETHERTYPE_PAE));
  571. if (is_mcast || is_eapol) {
  572. goto end;
  573. }
  574. ap_wiphy = ap_dev->ieee80211_ptr->wiphy;
  575. is_primary = qca_multi_link_is_primary_radio(ap_wiphy);
  576. if (is_primary) {
  577. goto end;
  578. } else {
  579. dev_hold(ap_dev);
  580. status = qca_multi_link_secondary_ap_rx(ap_dev, nbuf);
  581. dev_put(ap_dev);
  582. }
  583. if (status == QCA_MULTI_LINK_PKT_ALLOW) {
  584. goto end;
  585. } else if (status == QCA_MULTI_LINK_PKT_CONSUMED) {
  586. return true;
  587. } else if (status == QCA_MULTI_LINK_PKT_DROP) {
  588. drop_packet = true;
  589. }
  590. end:
  591. if (drop_packet) {
  592. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  593. FL("\n STA TX - Drop Packet for Mac=%pM\n"), eh->ether_shost);
  594. qdf_nbuf_free(nbuf);
  595. return true;
  596. }
  597. return false;
  598. }
  599. qdf_export_symbol(qca_multi_link_ap_rx);
  600. /**
  601. * qca_multi_link_secondary_sta_rx() - Processing for frames recieved on secondary station vap
  602. * @net_dev: station net device
  603. * @nbuf: frame
  604. *
  605. * Return: @qca_multi_link_status_t
  606. * QCA_MULTI_LINK_PKT_ALLOW: frame should be processed further by caller
  607. * QCA_MULTI_LINK_PKT_DROP: frame to be dropped.
  608. * QCA_MULTI_LINK_PKT_CONSUMED: frame is consumed.
  609. */
  610. static qca_multi_link_status_t qca_multi_link_secondary_sta_rx(struct net_device *net_dev,
  611. qdf_nbuf_t nbuf)
  612. {
  613. uint8_t is_mcast;
  614. qca_multi_link_tbl_entry_t qca_ml_entry;
  615. struct wiphy *sta_wiphy = NULL;
  616. struct net_device *sta_dev = net_dev;
  617. struct net_device *ap_dev = NULL;
  618. QDF_STATUS qal_status = QDF_STATUS_E_FAILURE;
  619. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  620. sta_wiphy = sta_dev->ieee80211_ptr->wiphy;
  621. is_mcast = IEEE80211_IS_MULTICAST(eh->ether_dhost);
  622. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("Secondary STA Rx:always_primary=%d, loop_detected=%d,\
  623. drop_secondary_mcast=%d, shost %pM dhost %pM is_mcast=%d\n"),
  624. qca_multi_link_cfg.always_primary, qca_multi_link_cfg.loop_detected,
  625. qca_multi_link_cfg.drop_secondary_mcast, eh->ether_shost, eh->ether_dhost, is_mcast);
  626. /*
  627. * Mcast packets handling.
  628. */
  629. if (is_mcast) {
  630. /*
  631. * Always drop mcast packets on secondary radio when loop has been detected.
  632. */
  633. if (qca_multi_link_cfg.loop_detected) {
  634. return QCA_MULTI_LINK_PKT_DROP;
  635. }
  636. qca_ml_entry.qal_fdb_ieee80211_ptr = NULL;
  637. qca_ml_entry.qal_fdb_dev = NULL;
  638. qca_ml_entry.qal_fdb_is_local = 0;
  639. qal_status = qca_multi_link_tbl_has_entry(sta_dev, eh->ether_shost, 0,
  640. &qca_ml_entry);
  641. if (qal_status != QDF_STATUS_SUCCESS) {
  642. if (!qca_multi_link_cfg.loop_detected
  643. && !qca_multi_link_cfg.drop_secondary_mcast) {
  644. /*
  645. * This condition is to allow packets on Secondary Station
  646. * when stations are connected to different RootAPs and loop is not
  647. * detected.
  648. */
  649. return QCA_MULTI_LINK_PKT_ALLOW;
  650. } else {
  651. return QCA_MULTI_LINK_PKT_DROP;
  652. }
  653. }
  654. /*
  655. * Case 1:
  656. * ieee80211_ptr pointer being NULL indicates that the port
  657. * corresponding to the fdb entry is a non-wireless/ethernet
  658. * device behind the repeater and the packet is a mcast looped packet.
  659. * Case 2:
  660. * ieee80211_ptr pointer being non NULL indicates that the source
  661. * corresponding to the fdb entry is a wireless device
  662. * behind the repeater and the packet is a mcast looped packet.
  663. */
  664. if (qca_ml_entry.qal_fdb_ieee80211_ptr && (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_wiphy)) {
  665. if (!qca_multi_link_cfg.loop_detected) {
  666. if (qca_ml_entry.qal_fdb_is_local
  667. && (qca_ml_entry.qal_fdb_ieee80211_ptr->iftype == NL80211_IFTYPE_STATION)) {
  668. qca_multi_link_cfg.loop_detected = true;
  669. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO, FL("\n****Wifi Rptr Loop Detected****\n"));
  670. }
  671. }
  672. return QCA_MULTI_LINK_PKT_DROP;
  673. }
  674. if (qca_multi_link_drop_secondary_mcast(nbuf)) {
  675. return QCA_MULTI_LINK_PKT_DROP;
  676. }
  677. /*
  678. * If the mac-address is learnt on the station in the bridge,
  679. * then the mcast packet is from a source on the RootAP side and we
  680. * should allow the packet.
  681. * This check on secondary will take of the case where stations are connected to different RootAPs
  682. * and loop is not detected.
  683. */
  684. if (qca_ml_entry.qal_fdb_dev == sta_dev) {
  685. return QCA_MULTI_LINK_PKT_ALLOW;
  686. }
  687. return QCA_MULTI_LINK_PKT_DROP;
  688. }
  689. /*
  690. * Unicast packets handling received on secondary Stations.
  691. */
  692. if (qca_multi_link_cfg.loop_detected) {
  693. qca_ml_entry.qal_fdb_ieee80211_ptr = NULL;
  694. qca_ml_entry.qal_fdb_dev = NULL;
  695. qca_ml_entry.qal_fdb_is_local = 0;
  696. qal_status = qca_multi_link_tbl_has_entry(sta_dev, eh->ether_dhost, 0,
  697. &qca_ml_entry);
  698. if (qal_status == QDF_STATUS_SUCCESS) {
  699. /*
  700. * Unicast packets destined to ethernets or bridge should never come
  701. * on secondary stations.
  702. */
  703. if (!qca_ml_entry.qal_fdb_ieee80211_ptr) {
  704. return QCA_MULTI_LINK_PKT_DROP;
  705. }
  706. /*
  707. * Compare the physical device and check if the destination is a client
  708. * on the same radio, then enqueue directly to AP vap.
  709. */
  710. if ((qca_ml_entry.qal_fdb_ieee80211_ptr->iftype == NL80211_IFTYPE_AP)
  711. && (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy == sta_wiphy)) {
  712. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("Unicast Sec STA to AP direct enq for\
  713. shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
  714. /*
  715. * Holding the AP dev so that it cannot be brought down
  716. * while we are enqueueing.
  717. */
  718. dev_hold(qca_ml_entry.qal_fdb_dev);
  719. qca_ml_entry.qal_fdb_dev->netdev_ops->ndo_start_xmit(nbuf, qca_ml_entry.qal_fdb_dev);
  720. dev_put(qca_ml_entry.qal_fdb_dev);
  721. return QCA_MULTI_LINK_PKT_CONSUMED;
  722. }
  723. return QCA_MULTI_LINK_PKT_DROP;
  724. } else {
  725. /*
  726. * If there is no bridge fdb entry for unicast packets received on secondary
  727. * station, give the packet to the first found AP vap entry in the bridge table.
  728. */
  729. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("No Fdb entry on sec radio\
  730. for ucast pkt with dhost %pM \n"), eh->ether_dhost);
  731. /*
  732. * Find the AP vap corresponding to the station vap.
  733. */
  734. ap_dev = qca_multi_link_tbl_find_sta_or_ap(sta_dev, 0);
  735. if (!ap_dev) {
  736. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  737. FL("Null AP device found %pM - Give to bridge\n"), eh->ether_shost);
  738. return QCA_MULTI_LINK_PKT_DROP;
  739. }
  740. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  741. FL("shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
  742. /*
  743. * For packets destined to sources on RootAP directly enq to STA vap.
  744. */
  745. dev_hold(ap_dev);
  746. ap_dev->netdev_ops->ndo_start_xmit(nbuf, ap_dev);
  747. dev_put(ap_dev);
  748. return QCA_MULTI_LINK_PKT_CONSUMED;
  749. }
  750. }
  751. return QCA_MULTI_LINK_PKT_ALLOW;
  752. }
  753. /**
  754. * qca_multi_link_primary_sta_rx() - Processing for frames recieved on primary station vap
  755. * @net_dev: station net device
  756. * @nbuf: frame
  757. *
  758. * Return: @qca_multi_link_status_t
  759. * QCA_MULTI_LINK_PKT_ALLOW: frame should be processed further by caller
  760. * QCA_MULTI_LINK_PKT_DROP: frame to be dropped
  761. * QCA_MULTI_LINK_PKT_CONSUMED: frame is consumed.
  762. */
  763. static qca_multi_link_status_t qca_multi_link_primary_sta_rx(struct net_device *net_dev, qdf_nbuf_t nbuf)
  764. {
  765. uint8_t is_mcast;
  766. qca_multi_link_tbl_entry_t qca_ml_entry;
  767. struct wiphy *sta_wiphy = NULL;
  768. struct net_device *sta_dev = net_dev;
  769. QDF_STATUS qal_status = QDF_STATUS_E_FAILURE;
  770. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  771. sta_wiphy = sta_dev->ieee80211_ptr->wiphy;
  772. is_mcast = IEEE80211_IS_MULTICAST(eh->ether_dhost);
  773. /*
  774. * Unicast Packets are allowed without any processing on Primary Station Vap.
  775. */
  776. if (!is_mcast) {
  777. return QCA_MULTI_LINK_PKT_ALLOW;
  778. }
  779. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("Primary STA Rx: always_primary=%d, loop_detected=%d,\
  780. drop_secondary_mcast=%d, shost %pM dhost %pM is_mcast=%d\n"),
  781. qca_multi_link_cfg.always_primary, qca_multi_link_cfg.loop_detected,
  782. qca_multi_link_cfg.drop_secondary_mcast, eh->ether_shost, eh->ether_dhost, is_mcast);
  783. /*
  784. * Mcast packet handling on Primary Station Vap Interface.
  785. */
  786. qca_ml_entry.qal_fdb_ieee80211_ptr = NULL;
  787. qca_ml_entry.qal_fdb_dev = NULL;
  788. qca_ml_entry.qal_fdb_is_local = 0;
  789. qal_status = qca_multi_link_tbl_has_entry(sta_dev, eh->ether_shost, 0,
  790. &qca_ml_entry);
  791. if (qal_status != QDF_STATUS_SUCCESS) {
  792. if (qca_multi_link_cfg.loop_detected) {
  793. /*
  794. * If there is no fdb entry, the we allow the packet to go to
  795. * bridge as this might be the first packet from any device
  796. * on the RootAP side.
  797. */
  798. return QCA_MULTI_LINK_PKT_ALLOW;
  799. }
  800. return QCA_MULTI_LINK_PKT_DROP;
  801. }
  802. /*
  803. * Case 1:
  804. * ieee80211_ptr pointer being NULL indicates that the port
  805. * corresponding to the fdb entry is a non-wireless/ethernet
  806. * device behind the repeater and the packet is a mcast looped packet.
  807. * Case 2:
  808. * ieee80211_ptr pointer being non NULL indicates that the source
  809. * corresponding to the fdb entry is a wireless device
  810. * behind the repeater and the packet is a mcast looped packet.
  811. */
  812. /*
  813. * Drop the loopback mcast packets from ethernet devices behind the repeater.
  814. */
  815. if (!qca_ml_entry.qal_fdb_ieee80211_ptr) {
  816. return QCA_MULTI_LINK_PKT_DROP;
  817. }
  818. if (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_wiphy) {
  819. if (!qca_multi_link_cfg.loop_detected) {
  820. if (qca_ml_entry.qal_fdb_is_local
  821. && (qca_ml_entry.qal_fdb_ieee80211_ptr->iftype == NL80211_IFTYPE_STATION)) {
  822. qca_multi_link_cfg.loop_detected = true;
  823. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_INFO,
  824. FL("\n****Wifi Rptr Loop Detected****\n"));
  825. }
  826. }
  827. return QCA_MULTI_LINK_PKT_DROP;
  828. }
  829. /*
  830. * If the mac-address is learnt on the Primary station in the bridge,
  831. * then the mcast packet is from a source on the RootAP side and we
  832. * should allow the packet.
  833. */
  834. if (qca_ml_entry.qal_fdb_dev == sta_dev) {
  835. return QCA_MULTI_LINK_PKT_ALLOW;
  836. }
  837. return QCA_MULTI_LINK_PKT_DROP;
  838. }
  839. /**
  840. * qca_multi_link_sta_rx() - Processing for frames recieved on STA VAP
  841. * @net_dev: station net device
  842. * @nbuf: frame
  843. *
  844. * Return: false: frame not consumed and should be processed further by caller
  845. * true: frame dropped/enqueued.
  846. */
  847. bool qca_multi_link_sta_rx(struct net_device *net_dev, qdf_nbuf_t nbuf)
  848. {
  849. uint8_t is_eapol;
  850. bool is_primary = false;
  851. struct wiphy *sta_wiphy = NULL;
  852. struct net_device *sta_dev = net_dev;
  853. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  854. bool drop_packet = false;
  855. qca_multi_link_status_t status = QCA_MULTI_LINK_PKT_NONE;
  856. if (!qca_multi_link_need_procesing()) {
  857. goto end;
  858. }
  859. is_eapol = (eh->ether_type == htons(ETHERTYPE_PAE));
  860. if (is_eapol) {
  861. goto end;
  862. }
  863. sta_wiphy = sta_dev->ieee80211_ptr->wiphy;
  864. is_primary = qca_multi_link_is_primary_radio(sta_wiphy);
  865. if (qca_multi_link_drop_always_primary(is_primary, nbuf)) {
  866. drop_packet = true;
  867. goto end;
  868. }
  869. dev_hold(sta_dev);
  870. if (is_primary) {
  871. status = qca_multi_link_primary_sta_rx(sta_dev, nbuf);
  872. } else {
  873. status = qca_multi_link_secondary_sta_rx(sta_dev, nbuf);
  874. }
  875. dev_put(sta_dev);
  876. if (status == QCA_MULTI_LINK_PKT_ALLOW) {
  877. goto end;
  878. } else if (status == QCA_MULTI_LINK_PKT_CONSUMED) {
  879. return true;
  880. } else if (status == QCA_MULTI_LINK_PKT_DROP) {
  881. drop_packet = true;
  882. }
  883. end:
  884. if (drop_packet) {
  885. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  886. FL("\n STA TX - Drop Packet for Mac=%pM\n"), eh->ether_shost);
  887. qdf_nbuf_free(nbuf);
  888. return true;
  889. }
  890. return false;
  891. }
  892. qdf_export_symbol(qca_multi_link_sta_rx);
  893. /**
  894. * qca_multi_link_secondary_sta_tx() - Repeater TX processing for Secondary
  895. * @net_device: station net device handle
  896. * @nbuf: frame
  897. *
  898. * Return: @qca_multi_link_status_t
  899. * QCA_MULTI_LINK_PKT_ALLOW: frame should be processed further by caller
  900. * QCA_MULTI_LINK_PKT_DROP: frame to be dropped
  901. * QCA_MULTI_LINK_PKT_CONSUMED: frame is consumed.
  902. */
  903. static qca_multi_link_status_t qca_multi_link_secondary_sta_tx(struct net_device *net_dev, qdf_nbuf_t nbuf)
  904. {
  905. uint8_t is_mcast;
  906. struct wiphy *sta_wiphy = NULL;
  907. struct net_device *sta_dev = net_dev;
  908. qca_multi_link_tbl_entry_t qca_ml_entry;
  909. QDF_STATUS qal_status = QDF_STATUS_E_FAILURE;
  910. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  911. if (qca_multi_link_drop_always_primary(false, nbuf)) {
  912. return QCA_MULTI_LINK_PKT_DROP;
  913. }
  914. sta_wiphy = sta_dev->ieee80211_ptr->wiphy;
  915. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("STA Secondary Tx: always_primary=%d, loop_detected=%d,\
  916. drop_secondary_mcast=%d, shost %pM dhost %pM \n"),
  917. qca_multi_link_cfg.always_primary, qca_multi_link_cfg.loop_detected, qca_multi_link_cfg.drop_secondary_mcast,
  918. eh->ether_shost, eh->ether_dhost);
  919. /*
  920. * For a Secondary station, only Packets from clients on the same band are allowed for transmit.
  921. */
  922. is_mcast = IEEE80211_IS_MULTICAST(eh->ether_dhost);
  923. qca_ml_entry.qal_fdb_ieee80211_ptr = NULL;
  924. qca_ml_entry.qal_fdb_dev = NULL;
  925. qca_ml_entry.qal_fdb_is_local = 0;
  926. qal_status = qca_multi_link_tbl_has_entry(sta_dev, eh->ether_shost, 0,
  927. &qca_ml_entry);
  928. if (qal_status != QDF_STATUS_SUCCESS) {
  929. if (!is_mcast) {
  930. return QCA_MULTI_LINK_PKT_ALLOW;
  931. }
  932. return QCA_MULTI_LINK_PKT_DROP;
  933. }
  934. if (!qca_ml_entry.qal_fdb_ieee80211_ptr) {
  935. /*
  936. * ieee80211_ptr pointer will be NULL for ethernet devices.
  937. * Packets from ethernet devices or bridge are allowed only on Primary radio.
  938. */
  939. return QCA_MULTI_LINK_PKT_DROP;
  940. }
  941. /*
  942. * Do the DBDC Fast Lane processing at the beginning and then fall back to normal DBDC STA TX
  943. * if either fast-lane is disabled or the TX is for non-fast lane radio.
  944. */
  945. if (is_fast_lane_radio(sta_wiphy) && is_fast_lane_radio(qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy)) {
  946. return QCA_MULTI_LINK_PKT_ALLOW;
  947. }
  948. if (qca_multi_link_drop_secondary_mcast(nbuf)) {
  949. return QCA_MULTI_LINK_PKT_DROP;
  950. }
  951. /*
  952. * Compare the physical device and check if the source is a client
  953. * on the same radio.
  954. */
  955. if (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_dev->ieee80211_ptr->wiphy) {
  956. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("STA TX: Diff Band Primary drop\
  957. shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
  958. return QCA_MULTI_LINK_PKT_DROP;
  959. }
  960. return QCA_MULTI_LINK_PKT_ALLOW;
  961. }
  962. /**
  963. * qca_multi_link_primary_sta_tx() - Repeater TX processing for Primary
  964. * @net_device: station net device handle
  965. * @nbuf: frame
  966. *
  967. * Return: @qca_multi_link_status_t
  968. * QCA_MULTI_LINK_PKT_ALLOW: frame should be processed further by caller
  969. * QCA_MULTI_LINK_PKT_DROP: frame to be dropped
  970. * QCA_MULTI_LINK_PKT_CONSUMED: frame is consumed.
  971. */
  972. static qca_multi_link_status_t qca_multi_link_primary_sta_tx(struct net_device *net_dev, qdf_nbuf_t nbuf)
  973. {
  974. struct wiphy *sta_wiphy = NULL;
  975. struct net_device *sta_dev = net_dev;
  976. qca_multi_link_tbl_entry_t qca_ml_entry;
  977. QDF_STATUS qal_status = QDF_STATUS_E_FAILURE;
  978. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  979. sta_wiphy = sta_dev->ieee80211_ptr->wiphy;
  980. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("Primary STA Tx: always_primary=%d, loop_detected=%d,\
  981. drop_secondary_mcast=%d, shost %pM dhost %pM \n"),
  982. qca_multi_link_cfg.always_primary, qca_multi_link_cfg.loop_detected,
  983. qca_multi_link_cfg.drop_secondary_mcast, eh->ether_shost, eh->ether_dhost);
  984. /*
  985. * For Primary station, packets allowed for transmission are:
  986. * 1) Packets from ethernet devices.
  987. * 2) Packets from radios which are not participating in backhaul.
  988. * 3) Packets from clients on the same band.
  989. */
  990. qca_ml_entry.qal_fdb_ieee80211_ptr = NULL;
  991. qca_ml_entry.qal_fdb_dev = NULL;
  992. qca_ml_entry.qal_fdb_is_local = 0;
  993. qal_status = qca_multi_link_tbl_has_entry(sta_dev, eh->ether_shost, 0,
  994. &qca_ml_entry);
  995. /*
  996. * All packets coming to Primary station has to have a bridge fdb entry
  997. * as they will be received from bridge only.
  998. */
  999. if (qal_status != QDF_STATUS_SUCCESS) {
  1000. return QCA_MULTI_LINK_PKT_DROP;
  1001. }
  1002. if (!qca_ml_entry.qal_fdb_ieee80211_ptr) {
  1003. /*
  1004. * ieee80211_ptr pointer will be NULL for ethernet devices.
  1005. * Packets from ethernet devices or bridge are allowed only on Primary radio.
  1006. */
  1007. return QCA_MULTI_LINK_PKT_ALLOW;
  1008. }
  1009. /*
  1010. * Do the DBDC Fast Lane processing at the beginning and then fall back to normal DBDC STA TX
  1011. * if either fast-lane is disabled or the TX is for non-fast lane radio.
  1012. */
  1013. if (is_fast_lane_radio(sta_wiphy)
  1014. && is_fast_lane_radio(qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy)) {
  1015. return QCA_MULTI_LINK_PKT_ALLOW;
  1016. }
  1017. /*
  1018. * This flag will be set for radios which does not particpate in backhaul.
  1019. */
  1020. if (is_no_backhaul_radio(qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy)) {
  1021. return QCA_MULTI_LINK_PKT_ALLOW;
  1022. }
  1023. /*
  1024. * Compare the physical device and check if the source is a client
  1025. * on the same radio.
  1026. */
  1027. if (qca_ml_entry.qal_fdb_ieee80211_ptr->wiphy != sta_dev->ieee80211_ptr->wiphy) {
  1028. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG, FL("STA TX: Diff Band Primary drop\
  1029. shost %pM dhost %pM \n"), eh->ether_shost, eh->ether_dhost);
  1030. return QCA_MULTI_LINK_PKT_DROP;
  1031. }
  1032. return QCA_MULTI_LINK_PKT_ALLOW;
  1033. }
  1034. /**
  1035. * qca_multi_link_sta_tx() - Repeater TX processing
  1036. * @net_device: station net device handle
  1037. * @nbuf: frame
  1038. *
  1039. * Return: false: frame not consumed and should be processed further by caller
  1040. * true: frame consumed
  1041. */
  1042. bool qca_multi_link_sta_tx(struct net_device *net_dev, qdf_nbuf_t nbuf)
  1043. {
  1044. bool drop_packet = false;
  1045. bool is_primary = false;
  1046. struct wiphy *sta_wiphy = NULL;
  1047. struct net_device *sta_dev = net_dev;
  1048. qdf_ether_header_t *eh = (qdf_ether_header_t *) qdf_nbuf_data(nbuf);
  1049. qca_multi_link_status_t status = QCA_MULTI_LINK_PKT_NONE;
  1050. if (!qca_multi_link_need_procesing()) {
  1051. goto end;
  1052. }
  1053. if (!qca_multi_link_cfg.loop_detected) {
  1054. goto end;
  1055. }
  1056. if (qca_multi_link_pktfrom_ownsrc(sta_dev, nbuf)) {
  1057. goto end;
  1058. }
  1059. sta_wiphy = sta_dev->ieee80211_ptr->wiphy;
  1060. is_primary = qca_multi_link_is_primary_radio(sta_wiphy);
  1061. dev_hold(net_dev);
  1062. if (is_primary) {
  1063. status = qca_multi_link_primary_sta_tx(sta_dev, nbuf);
  1064. } else {
  1065. status = qca_multi_link_secondary_sta_tx(sta_dev, nbuf);
  1066. }
  1067. dev_put(net_dev);
  1068. if (status == QCA_MULTI_LINK_PKT_ALLOW) {
  1069. goto end;
  1070. } else if (status == QCA_MULTI_LINK_PKT_CONSUMED) {
  1071. return true;
  1072. } else if (status == QCA_MULTI_LINK_PKT_DROP) {
  1073. drop_packet = true;
  1074. }
  1075. end:
  1076. if (drop_packet) {
  1077. QDF_TRACE(QDF_MODULE_ID_RPTR, QDF_TRACE_LEVEL_DEBUG,
  1078. FL("\n STA TX - Drop Packet for Mac=%pM\n"), eh->ether_shost);
  1079. qdf_nbuf_free(nbuf);
  1080. return true;
  1081. }
  1082. return false;
  1083. }
  1084. qdf_export_symbol(qca_multi_link_sta_tx);