wlan_cfg80211_tdls.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /*
  2. * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /**
  19. * DOC: defines driver functions interfacing with linux kernel
  20. */
  21. #include <qdf_list.h>
  22. #include <qdf_status.h>
  23. #include <linux/wireless.h>
  24. #include <linux/netdevice.h>
  25. #include <net/cfg80211.h>
  26. #include <wlan_cfg80211.h>
  27. #include <wlan_cfg80211_tdls.h>
  28. #include <wlan_osif_priv.h>
  29. #include <wlan_tdls_public_structs.h>
  30. #include <wlan_tdls_ucfg_api.h>
  31. #include <qdf_mem.h>
  32. #include <wlan_utility.h>
  33. #include <wlan_reg_services_api.h>
  34. #ifdef QCA_SUPPORT_CP_STATS
  35. #include "wlan_cfg80211_mc_cp_stats.h"
  36. #endif
  37. #define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS)
  38. #define TDLS_MAX_NO_OF_2_4_CHANNELS 14
  39. static int wlan_cfg80211_tdls_validate_mac_addr(const uint8_t *mac)
  40. {
  41. static const uint8_t temp_mac[QDF_MAC_ADDR_SIZE] = {0};
  42. if (!qdf_mem_cmp(mac, temp_mac, QDF_MAC_ADDR_SIZE)) {
  43. osif_debug("Invalid Mac address " QDF_MAC_ADDR_STR
  44. " cmd declined.",
  45. QDF_MAC_ADDR_ARRAY(mac));
  46. return -EINVAL;
  47. }
  48. return 0;
  49. }
  50. QDF_STATUS wlan_cfg80211_tdls_osif_priv_init(struct wlan_objmgr_vdev *vdev)
  51. {
  52. struct osif_tdls_vdev *tdls_priv;
  53. struct vdev_osif_priv *osif_priv;
  54. osif_priv = wlan_vdev_get_ospriv(vdev);
  55. if (!osif_priv) {
  56. osif_err("osif_priv is NULL!");
  57. return QDF_STATUS_E_FAULT;
  58. }
  59. osif_debug("initialize tdls os if layer private structure");
  60. tdls_priv = qdf_mem_malloc(sizeof(*tdls_priv));
  61. if (!tdls_priv) {
  62. osif_err("failed to allocate memory for tdls_priv");
  63. return QDF_STATUS_E_NOMEM;
  64. }
  65. init_completion(&tdls_priv->tdls_add_peer_comp);
  66. init_completion(&tdls_priv->tdls_del_peer_comp);
  67. init_completion(&tdls_priv->tdls_mgmt_comp);
  68. init_completion(&tdls_priv->tdls_link_establish_req_comp);
  69. init_completion(&tdls_priv->tdls_teardown_comp);
  70. init_completion(&tdls_priv->tdls_user_cmd_comp);
  71. init_completion(&tdls_priv->tdls_antenna_switch_comp);
  72. osif_priv->osif_tdls = tdls_priv;
  73. return QDF_STATUS_SUCCESS;
  74. }
  75. void wlan_cfg80211_tdls_osif_priv_deinit(struct wlan_objmgr_vdev *vdev)
  76. {
  77. struct vdev_osif_priv *osif_priv;
  78. osif_priv = wlan_vdev_get_ospriv(vdev);
  79. if (!osif_priv) {
  80. osif_err("osif_priv is NULL!");
  81. return;
  82. }
  83. osif_debug("deinitialize tdls os if layer private structure");
  84. if (osif_priv->osif_tdls)
  85. qdf_mem_free(osif_priv->osif_tdls);
  86. osif_priv->osif_tdls = NULL;
  87. }
  88. void hdd_notify_teardown_tdls_links(struct wlan_objmgr_psoc *psoc)
  89. {
  90. struct vdev_osif_priv *osif_priv;
  91. struct osif_tdls_vdev *tdls_priv;
  92. QDF_STATUS status;
  93. unsigned long rc;
  94. struct wlan_objmgr_vdev *vdev;
  95. vdev = ucfg_get_tdls_vdev(psoc, WLAN_OSIF_ID);
  96. if (!vdev) {
  97. osif_err("Unable to get the vdev");
  98. return;
  99. }
  100. osif_priv = wlan_vdev_get_ospriv(vdev);
  101. if (!osif_priv || !osif_priv->osif_tdls) {
  102. osif_err("osif priv or tdls priv is NULL");
  103. goto release_ref;
  104. }
  105. tdls_priv = osif_priv->osif_tdls;
  106. reinit_completion(&tdls_priv->tdls_teardown_comp);
  107. status = ucfg_tdls_teardown_links(psoc);
  108. if (QDF_IS_STATUS_ERROR(status)) {
  109. osif_err("ucfg_tdls_teardown_links failed err %d", status);
  110. goto release_ref;
  111. }
  112. osif_debug("Wait for tdls teardown completion. Timeout %u ms",
  113. WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS);
  114. rc = wait_for_completion_timeout(
  115. &tdls_priv->tdls_teardown_comp,
  116. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS));
  117. if (0 == rc) {
  118. osif_err(" Teardown Completion timed out rc: %ld", rc);
  119. goto release_ref;
  120. }
  121. osif_debug("TDLS teardown completion status %ld ", rc);
  122. release_ref:
  123. wlan_objmgr_vdev_release_ref(vdev,
  124. WLAN_OSIF_ID);
  125. }
  126. void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
  127. {
  128. ucfg_tdls_notify_reset_adapter(vdev);
  129. }
  130. void
  131. hdd_notify_sta_connect(uint8_t session_id,
  132. bool tdls_chan_swit_prohibited,
  133. bool tdls_prohibited,
  134. struct wlan_objmgr_vdev *vdev)
  135. {
  136. struct tdls_sta_notify_params notify_info = {0};
  137. QDF_STATUS status;
  138. if (!vdev) {
  139. osif_err("vdev is NULL");
  140. return;
  141. }
  142. status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
  143. if (QDF_IS_STATUS_ERROR(status)) {
  144. osif_err("can't get vdev");
  145. return;
  146. }
  147. notify_info.session_id = session_id;
  148. notify_info.vdev = vdev;
  149. notify_info.tdls_chan_swit_prohibited = tdls_chan_swit_prohibited;
  150. notify_info.tdls_prohibited = tdls_prohibited;
  151. ucfg_tdls_notify_sta_connect(&notify_info);
  152. }
  153. void hdd_notify_sta_disconnect(uint8_t session_id,
  154. bool lfr_roam,
  155. bool user_disconnect,
  156. struct wlan_objmgr_vdev *vdev)
  157. {
  158. struct tdls_sta_notify_params notify_info = {0};
  159. QDF_STATUS status;
  160. if (!vdev) {
  161. osif_err("vdev is NULL");
  162. return;
  163. }
  164. status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
  165. if (QDF_IS_STATUS_ERROR(status)) {
  166. osif_err("can't get vdev");
  167. return;
  168. }
  169. notify_info.session_id = session_id;
  170. notify_info.lfr_roam = lfr_roam;
  171. notify_info.tdls_chan_swit_prohibited = false;
  172. notify_info.tdls_prohibited = false;
  173. notify_info.vdev = vdev;
  174. notify_info.user_disconnect = user_disconnect;
  175. ucfg_tdls_notify_sta_disconnect(&notify_info);
  176. }
  177. int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
  178. const uint8_t *mac)
  179. {
  180. struct tdls_add_peer_params *add_peer_req;
  181. int status;
  182. struct vdev_osif_priv *osif_priv;
  183. struct osif_tdls_vdev *tdls_priv;
  184. unsigned long rc;
  185. status = wlan_cfg80211_tdls_validate_mac_addr(mac);
  186. if (status)
  187. return status;
  188. osif_debug("Add TDLS peer " QDF_MAC_ADDR_STR,
  189. QDF_MAC_ADDR_ARRAY(mac));
  190. add_peer_req = qdf_mem_malloc(sizeof(*add_peer_req));
  191. if (!add_peer_req) {
  192. osif_err("Failed to allocate tdls add peer request mem");
  193. return -EINVAL;
  194. }
  195. osif_priv = wlan_vdev_get_ospriv(vdev);
  196. if (!osif_priv || !osif_priv->osif_tdls) {
  197. osif_err("osif_tdls_vdev or osif_priv is NULL for the current vdev");
  198. status = -EINVAL;
  199. goto error;
  200. }
  201. tdls_priv = osif_priv->osif_tdls;
  202. add_peer_req->vdev_id = wlan_vdev_get_id(vdev);
  203. qdf_mem_copy(add_peer_req->peer_addr, mac, QDF_MAC_ADDR_SIZE);
  204. reinit_completion(&tdls_priv->tdls_add_peer_comp);
  205. status = ucfg_tdls_add_peer(vdev, add_peer_req);
  206. if (QDF_IS_STATUS_ERROR(status)) {
  207. osif_err("ucfg_tdls_add_peer returned err %d", status);
  208. status = -EIO;
  209. goto error;
  210. }
  211. rc = wait_for_completion_timeout(
  212. &tdls_priv->tdls_add_peer_comp,
  213. msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
  214. if (!rc) {
  215. osif_err("timeout for tdls add peer indication %ld", rc);
  216. status = -EPERM;
  217. goto error;
  218. }
  219. if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
  220. osif_err("tdls add peer failed, status:%d",
  221. tdls_priv->tdls_add_peer_status);
  222. status = -EPERM;
  223. }
  224. error:
  225. qdf_mem_free(add_peer_req);
  226. return status;
  227. }
  228. static bool
  229. is_duplicate_channel(uint8_t *arr, int index, uint8_t match)
  230. {
  231. int i;
  232. for (i = 0; i < index; i++) {
  233. if (arr[i] == match)
  234. return true;
  235. }
  236. return false;
  237. }
  238. static void
  239. tdls_calc_channels_from_staparams(struct tdls_update_peer_params *req_info,
  240. struct station_parameters *params)
  241. {
  242. int i = 0, j = 0, k = 0, no_of_channels = 0;
  243. int num_unique_channels;
  244. int next;
  245. uint8_t *dest_chans;
  246. const uint8_t *src_chans;
  247. dest_chans = req_info->supported_channels;
  248. src_chans = params->supported_channels;
  249. /* Convert (first channel , number of channels) tuple to
  250. * the total list of channels. This goes with the assumption
  251. * that if the first channel is < 14, then the next channels
  252. * are an incremental of 1 else an incremental of 4 till the number
  253. * of channels.
  254. */
  255. for (i = 0; i < params->supported_channels_len &&
  256. j < WLAN_MAC_MAX_SUPP_CHANNELS; i += 2) {
  257. int wifi_chan_index;
  258. if (!is_duplicate_channel(dest_chans, j, src_chans[i]))
  259. dest_chans[j] = src_chans[i];
  260. else
  261. continue;
  262. wifi_chan_index = ((dest_chans[j] <= WLAN_CHANNEL_14) ? 1 : 4);
  263. no_of_channels = src_chans[i + 1];
  264. osif_debug("i:%d,j:%d,k:%d,[%d]:%d,index:%d,chans_num: %d",
  265. i, j, k, j,
  266. dest_chans[j],
  267. wifi_chan_index,
  268. no_of_channels);
  269. for (k = 1; k <= no_of_channels &&
  270. j < WLAN_MAC_MAX_SUPP_CHANNELS - 1; k++) {
  271. next = dest_chans[j] + wifi_chan_index;
  272. if (!is_duplicate_channel(dest_chans, j + 1, next))
  273. dest_chans[j + 1] = next;
  274. else
  275. continue;
  276. osif_debug("i: %d, j: %d, k: %d, [%d]: %d",
  277. i, j, k, j + 1, dest_chans[j + 1]);
  278. j += 1;
  279. }
  280. }
  281. num_unique_channels = j + 1;
  282. osif_debug("Unique Channel List: supported_channels ");
  283. for (i = 0; i < num_unique_channels; i++)
  284. osif_debug("[%d]: %d,", i, dest_chans[i]);
  285. if (MAX_CHANNEL < num_unique_channels)
  286. num_unique_channels = MAX_CHANNEL;
  287. req_info->supported_channels_len = num_unique_channels;
  288. osif_debug("After removing duplcates supported_channels_len: %d",
  289. req_info->supported_channels_len);
  290. }
  291. static void
  292. wlan_cfg80211_tdls_extract_params(struct tdls_update_peer_params *req_info,
  293. struct station_parameters *params)
  294. {
  295. int i;
  296. osif_debug("sta cap %d, uapsd_queue %d, max_sp %d",
  297. params->capability,
  298. params->uapsd_queues, params->max_sp);
  299. if (!req_info) {
  300. osif_err("reg_info is NULL");
  301. return;
  302. }
  303. req_info->capability = params->capability;
  304. req_info->uapsd_queues = params->uapsd_queues;
  305. req_info->max_sp = params->max_sp;
  306. if (params->supported_channels_len)
  307. tdls_calc_channels_from_staparams(req_info, params);
  308. if (params->supported_oper_classes_len > WLAN_MAX_SUPP_OPER_CLASSES) {
  309. osif_debug("received oper classes:%d, resetting it to max supported: %d",
  310. params->supported_oper_classes_len,
  311. WLAN_MAX_SUPP_OPER_CLASSES);
  312. params->supported_oper_classes_len = WLAN_MAX_SUPP_OPER_CLASSES;
  313. }
  314. qdf_mem_copy(req_info->supported_oper_classes,
  315. params->supported_oper_classes,
  316. params->supported_oper_classes_len);
  317. req_info->supported_oper_classes_len =
  318. params->supported_oper_classes_len;
  319. if (params->ext_capab_len)
  320. qdf_mem_copy(req_info->extn_capability, params->ext_capab,
  321. sizeof(req_info->extn_capability));
  322. if (params->ht_capa) {
  323. req_info->htcap_present = 1;
  324. qdf_mem_copy(&req_info->ht_cap, params->ht_capa,
  325. sizeof(struct htcap_cmn_ie));
  326. }
  327. req_info->supported_rates_len = params->supported_rates_len;
  328. /* Note : The Maximum sizeof supported_rates sent by the Supplicant is
  329. * 32. The supported_rates array , for all the structures propogating
  330. * till Add Sta to the firmware has to be modified , if the supplicant
  331. * (ieee80211) is modified to send more rates.
  332. */
  333. /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
  334. */
  335. if (req_info->supported_rates_len > WLAN_MAC_MAX_SUPP_RATES)
  336. req_info->supported_rates_len = WLAN_MAC_MAX_SUPP_RATES;
  337. if (req_info->supported_rates_len) {
  338. qdf_mem_copy(req_info->supported_rates,
  339. params->supported_rates,
  340. req_info->supported_rates_len);
  341. osif_debug("Supported Rates with Length %d",
  342. req_info->supported_rates_len);
  343. for (i = 0; i < req_info->supported_rates_len; i++)
  344. osif_debug("[%d]: %0x", i,
  345. req_info->supported_rates[i]);
  346. }
  347. if (params->vht_capa) {
  348. req_info->vhtcap_present = 1;
  349. qdf_mem_copy(&req_info->vht_cap, params->vht_capa,
  350. sizeof(struct vhtcap));
  351. }
  352. if (params->ht_capa || params->vht_capa ||
  353. (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
  354. req_info->is_qos_wmm_sta = true;
  355. }
  356. int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
  357. const uint8_t *mac,
  358. struct station_parameters *params)
  359. {
  360. struct tdls_update_peer_params *req_info;
  361. int status;
  362. struct vdev_osif_priv *osif_priv;
  363. struct osif_tdls_vdev *tdls_priv;
  364. unsigned long rc;
  365. status = wlan_cfg80211_tdls_validate_mac_addr(mac);
  366. if (status)
  367. return status;
  368. osif_debug("Update TDLS peer " QDF_MAC_ADDR_STR,
  369. QDF_MAC_ADDR_ARRAY(mac));
  370. req_info = qdf_mem_malloc(sizeof(*req_info));
  371. if (!req_info) {
  372. osif_err("Failed to allocate tdls add peer request mem");
  373. return -EINVAL;
  374. }
  375. wlan_cfg80211_tdls_extract_params(req_info, params);
  376. osif_priv = wlan_vdev_get_ospriv(vdev);
  377. if (!osif_priv || !osif_priv->osif_tdls) {
  378. osif_err("osif priv or tdls priv is NULL");
  379. status = -EINVAL;
  380. goto error;
  381. }
  382. tdls_priv = osif_priv->osif_tdls;
  383. req_info->vdev_id = wlan_vdev_get_id(vdev);
  384. qdf_mem_copy(req_info->peer_addr, mac, QDF_MAC_ADDR_SIZE);
  385. reinit_completion(&tdls_priv->tdls_add_peer_comp);
  386. status = ucfg_tdls_update_peer(vdev, req_info);
  387. if (QDF_IS_STATUS_ERROR(status)) {
  388. osif_err("ucfg_tdls_update_peer returned err %d", status);
  389. status = -EIO;
  390. goto error;
  391. }
  392. rc = wait_for_completion_timeout(
  393. &tdls_priv->tdls_add_peer_comp,
  394. msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
  395. if (!rc) {
  396. osif_err("timeout for tdls update peer indication %ld", rc);
  397. status = -EPERM;
  398. goto error;
  399. }
  400. if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
  401. osif_err("tdls update peer failed, status:%d",
  402. tdls_priv->tdls_add_peer_status);
  403. status = -EPERM;
  404. }
  405. error:
  406. qdf_mem_free(req_info);
  407. return status;
  408. }
  409. static char *tdls_oper_to_str(enum nl80211_tdls_operation oper)
  410. {
  411. switch (oper) {
  412. case NL80211_TDLS_ENABLE_LINK:
  413. return "TDLS_ENABLE_LINK";
  414. case NL80211_TDLS_DISABLE_LINK:
  415. return "TDLS_DISABLE_LINK";
  416. case NL80211_TDLS_TEARDOWN:
  417. return "TDLS_TEARDOWN";
  418. case NL80211_TDLS_SETUP:
  419. return "TDLS_SETUP";
  420. default:
  421. return "UNKNOWN:ERR";
  422. }
  423. }
  424. static enum tdls_command_type tdls_oper_to_cmd(enum nl80211_tdls_operation oper)
  425. {
  426. if (oper == NL80211_TDLS_ENABLE_LINK)
  427. return TDLS_CMD_ENABLE_LINK;
  428. else if (oper == NL80211_TDLS_DISABLE_LINK)
  429. return TDLS_CMD_DISABLE_LINK;
  430. else if (oper == NL80211_TDLS_TEARDOWN)
  431. return TDLS_CMD_REMOVE_FORCE_PEER;
  432. else if (oper == NL80211_TDLS_SETUP)
  433. return TDLS_CMD_CONFIG_FORCE_PEER;
  434. else
  435. return 0;
  436. }
  437. int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
  438. uint32_t trigger_mode)
  439. {
  440. enum tdls_feature_mode tdls_mode;
  441. struct tdls_set_mode_params set_mode_params;
  442. int status;
  443. if (!vdev)
  444. return -EINVAL;
  445. switch (trigger_mode) {
  446. case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT:
  447. tdls_mode = TDLS_SUPPORT_EXP_TRIG_ONLY;
  448. return 0;
  449. case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL:
  450. tdls_mode = TDLS_SUPPORT_EXT_CONTROL;
  451. break;
  452. case WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT:
  453. tdls_mode = TDLS_SUPPORT_IMP_MODE;
  454. return 0;
  455. default:
  456. osif_err("Invalid TDLS trigger mode");
  457. return -EINVAL;
  458. }
  459. osif_notice("cfg80211 tdls trigger mode %d", trigger_mode);
  460. set_mode_params.source = TDLS_SET_MODE_SOURCE_USER;
  461. set_mode_params.tdls_mode = tdls_mode;
  462. set_mode_params.update_last = false;
  463. set_mode_params.vdev = vdev;
  464. status = ucfg_tdls_set_operating_mode(&set_mode_params);
  465. return status;
  466. }
  467. int wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev *vdev,
  468. const uint8_t *peer,
  469. enum nl80211_tdls_operation oper)
  470. {
  471. struct vdev_osif_priv *osif_priv;
  472. struct osif_tdls_vdev *tdls_priv;
  473. int status;
  474. unsigned long rc;
  475. enum tdls_command_type cmd;
  476. status = wlan_cfg80211_tdls_validate_mac_addr(peer);
  477. if (status)
  478. return status;
  479. if (NL80211_TDLS_DISCOVERY_REQ == oper) {
  480. osif_warn(
  481. "We don't support in-driver setup/teardown/discovery");
  482. return -ENOTSUPP;
  483. }
  484. osif_debug("%s start", tdls_oper_to_str(oper));
  485. cmd = tdls_oper_to_cmd(oper);
  486. switch (oper) {
  487. case NL80211_TDLS_ENABLE_LINK:
  488. case NL80211_TDLS_TEARDOWN:
  489. case NL80211_TDLS_SETUP:
  490. status = ucfg_tdls_oper(vdev, peer, cmd);
  491. if (QDF_IS_STATUS_ERROR(status)) {
  492. osif_err("%s fail %d",
  493. tdls_oper_to_str(oper), status);
  494. status = -EIO;
  495. goto error;
  496. }
  497. break;
  498. case NL80211_TDLS_DISABLE_LINK:
  499. osif_priv = wlan_vdev_get_ospriv(vdev);
  500. if (!osif_priv || !osif_priv->osif_tdls) {
  501. osif_err("osif priv or tdls priv is NULL");
  502. status = -EINVAL;
  503. goto error;
  504. }
  505. tdls_priv = osif_priv->osif_tdls;
  506. reinit_completion(&tdls_priv->tdls_del_peer_comp);
  507. status = ucfg_tdls_oper(vdev, peer, cmd);
  508. if (QDF_IS_STATUS_ERROR(status)) {
  509. osif_err("ucfg_tdls_disable_link fail %d", status);
  510. status = -EIO;
  511. goto error;
  512. }
  513. rc = wait_for_completion_timeout(
  514. &tdls_priv->tdls_del_peer_comp,
  515. msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
  516. if (!rc) {
  517. osif_err("timeout for tdls disable link %ld", rc);
  518. status = -EPERM;
  519. }
  520. break;
  521. default:
  522. osif_err("unsupported event %d", oper);
  523. status = -ENOTSUPP;
  524. }
  525. error:
  526. return status;
  527. }
  528. void wlan_cfg80211_tdls_rx_callback(void *user_data,
  529. struct tdls_rx_mgmt_frame *rx_frame)
  530. {
  531. struct wlan_objmgr_psoc *psoc;
  532. struct wlan_objmgr_vdev *vdev;
  533. struct vdev_osif_priv *osif_priv;
  534. struct wireless_dev *wdev;
  535. uint16_t freq;
  536. osif_debug("user data:%pK, vdev id:%d, rssi:%d, buf:%pK, len:%d",
  537. user_data, rx_frame->vdev_id, rx_frame->rx_rssi,
  538. rx_frame->buf, rx_frame->frame_len);
  539. psoc = user_data;
  540. if (!psoc) {
  541. osif_err("psoc is null");
  542. return;
  543. }
  544. vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
  545. rx_frame->vdev_id, WLAN_TDLS_NB_ID);
  546. if (!vdev) {
  547. osif_err("vdev is null");
  548. return;
  549. }
  550. osif_priv = wlan_vdev_get_ospriv(vdev);
  551. if (!osif_priv) {
  552. osif_err("osif_priv is null");
  553. goto fail;
  554. }
  555. wdev = osif_priv->wdev;
  556. if (!wdev) {
  557. osif_err("wdev is null");
  558. goto fail;
  559. }
  560. if (rx_frame->rx_chan <= TDLS_MAX_NO_OF_2_4_CHANNELS)
  561. freq = ieee80211_channel_to_frequency(
  562. rx_frame->rx_chan, NL80211_BAND_2GHZ);
  563. else
  564. freq = ieee80211_channel_to_frequency(
  565. rx_frame->rx_chan, NL80211_BAND_5GHZ);
  566. osif_notice("Indicate frame over nl80211, vdev id:%d, idx:%d",
  567. rx_frame->vdev_id, wdev->netdev->ifindex);
  568. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  569. cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
  570. rx_frame->buf, rx_frame->frame_len,
  571. NL80211_RXMGMT_FLAG_ANSWERED);
  572. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  573. cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
  574. rx_frame->buf, rx_frame->frame_len,
  575. NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
  576. #else
  577. cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
  578. rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC);
  579. #endif /* LINUX_VERSION_CODE */
  580. fail:
  581. wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
  582. }
  583. #ifdef QCA_SUPPORT_CP_STATS
  584. static void wlan_cfg80211_update_tdls_peers_rssi(struct wlan_objmgr_vdev *vdev)
  585. {
  586. int ret = 0, i;
  587. struct stats_event *rssi_info;
  588. struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
  589. rssi_info = wlan_cfg80211_mc_cp_stats_get_peer_rssi(
  590. vdev, bcast_mac.bytes,
  591. &ret);
  592. if (ret || !rssi_info) {
  593. osif_err("get peer rssi fail");
  594. wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info);
  595. return;
  596. }
  597. for (i = 0; i < rssi_info->num_peer_stats; i++)
  598. ucfg_tdls_set_rssi(vdev, rssi_info->peer_stats[i].peer_macaddr,
  599. rssi_info->peer_stats[i].peer_rssi);
  600. wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info);
  601. }
  602. #else
  603. static void wlan_cfg80211_update_tdls_peers_rssi(struct wlan_objmgr_vdev *vdev)
  604. {
  605. }
  606. #endif
  607. int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
  608. char *buf, int buflen)
  609. {
  610. struct vdev_osif_priv *osif_priv;
  611. struct osif_tdls_vdev *tdls_priv;
  612. int32_t len;
  613. QDF_STATUS status;
  614. unsigned long rc;
  615. osif_priv = wlan_vdev_get_ospriv(vdev);
  616. if (!osif_priv || !osif_priv->osif_tdls) {
  617. osif_err("osif_tdls_vdev or osif_priv is NULL for the current vdev");
  618. return -EINVAL;
  619. }
  620. tdls_priv = osif_priv->osif_tdls;
  621. wlan_cfg80211_update_tdls_peers_rssi(vdev);
  622. reinit_completion(&tdls_priv->tdls_user_cmd_comp);
  623. status = ucfg_tdls_get_all_peers(vdev, buf, buflen);
  624. if (QDF_IS_STATUS_ERROR(status)) {
  625. osif_err("ucfg_tdls_get_all_peers failed err %d", status);
  626. len = scnprintf(buf, buflen,
  627. "\nucfg_tdls_send_mgmt failed\n");
  628. goto error_get_tdls_peers;
  629. }
  630. osif_debug("Wait for tdls_user_cmd_comp. Timeout %u ms",
  631. WAIT_TIME_FOR_TDLS_USER_CMD);
  632. rc = wait_for_completion_timeout(
  633. &tdls_priv->tdls_user_cmd_comp,
  634. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_USER_CMD));
  635. if (0 == rc) {
  636. osif_err("TDLS user cmd get all peers timed out rc %ld",
  637. rc);
  638. len = scnprintf(buf, buflen,
  639. "\nTDLS user cmd get all peers timed out\n");
  640. goto error_get_tdls_peers;
  641. }
  642. len = tdls_priv->tdls_user_cmd_len;
  643. error_get_tdls_peers:
  644. return len;
  645. }
  646. int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
  647. const uint8_t *peer_mac,
  648. uint8_t action_code, uint8_t dialog_token,
  649. uint16_t status_code, uint32_t peer_capability,
  650. const uint8_t *buf, size_t len)
  651. {
  652. struct tdls_action_frame_request mgmt_req;
  653. struct vdev_osif_priv *osif_priv;
  654. struct osif_tdls_vdev *tdls_priv;
  655. int status;
  656. unsigned long rc;
  657. struct tdls_set_responder_req set_responder;
  658. status = wlan_cfg80211_tdls_validate_mac_addr(peer_mac);
  659. if (status)
  660. return status;
  661. osif_priv = wlan_vdev_get_ospriv(vdev);
  662. if (!osif_priv || !osif_priv->osif_tdls) {
  663. osif_err("osif priv or tdls priv is NULL");
  664. return -EINVAL;
  665. }
  666. tdls_priv = osif_priv->osif_tdls;
  667. /* make sure doesn't call send_mgmt() while it is pending */
  668. if (TDLS_VDEV_MAGIC == tdls_priv->mgmt_tx_completion_status) {
  669. osif_err(QDF_MAC_ADDR_STR " action %d couldn't sent, as one is pending. return EBUSY",
  670. QDF_MAC_ADDR_ARRAY(peer_mac), action_code);
  671. return -EBUSY;
  672. }
  673. /* Reset TDLS VDEV magic */
  674. tdls_priv->mgmt_tx_completion_status = TDLS_VDEV_MAGIC;
  675. /*prepare the request */
  676. /* Validate the management Request */
  677. mgmt_req.chk_frame.action_code = action_code;
  678. qdf_mem_copy(mgmt_req.chk_frame.peer_mac, peer_mac, QDF_MAC_ADDR_SIZE);
  679. mgmt_req.chk_frame.dialog_token = dialog_token;
  680. mgmt_req.chk_frame.action_code = action_code;
  681. mgmt_req.chk_frame.status_code = status_code;
  682. mgmt_req.chk_frame.len = len;
  683. mgmt_req.vdev = vdev;
  684. mgmt_req.vdev_id = wlan_vdev_get_id(vdev);
  685. mgmt_req.session_id = mgmt_req.vdev_id;
  686. /* populate management req params */
  687. qdf_mem_copy(mgmt_req.tdls_mgmt.peer_mac.bytes,
  688. peer_mac, QDF_MAC_ADDR_SIZE);
  689. mgmt_req.tdls_mgmt.dialog = dialog_token;
  690. mgmt_req.tdls_mgmt.frame_type = action_code;
  691. mgmt_req.tdls_mgmt.len = len;
  692. mgmt_req.tdls_mgmt.peer_capability = peer_capability;
  693. mgmt_req.tdls_mgmt.status_code = mgmt_req.chk_frame.status_code;
  694. /*populate the additional IE's */
  695. mgmt_req.cmd_buf = buf;
  696. mgmt_req.len = len;
  697. reinit_completion(&tdls_priv->tdls_mgmt_comp);
  698. status = ucfg_tdls_send_mgmt_frame(&mgmt_req);
  699. if (QDF_IS_STATUS_ERROR(status)) {
  700. osif_err("ucfg_tdls_send_mgmt failed err %d", status);
  701. status = -EIO;
  702. tdls_priv->mgmt_tx_completion_status = false;
  703. goto error_mgmt_req;
  704. }
  705. osif_debug("Wait for tdls_mgmt_comp. Timeout %u ms",
  706. WAIT_TIME_FOR_TDLS_MGMT);
  707. rc = wait_for_completion_timeout(
  708. &tdls_priv->tdls_mgmt_comp,
  709. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_MGMT));
  710. if ((0 == rc) || (QDF_STATUS_SUCCESS !=
  711. tdls_priv->mgmt_tx_completion_status)) {
  712. osif_err("%s rc %ld mgmtTxCompletionStatus %u",
  713. !rc ? "Mgmt Tx Completion timed out" :
  714. "Mgmt Tx Completion failed",
  715. rc, tdls_priv->mgmt_tx_completion_status);
  716. tdls_priv->mgmt_tx_completion_status = false;
  717. status = -EINVAL;
  718. goto error_mgmt_req;
  719. }
  720. osif_debug("Mgmt Tx Completion status %ld TxCompletion %u",
  721. rc, tdls_priv->mgmt_tx_completion_status);
  722. if (TDLS_SETUP_RESPONSE == action_code ||
  723. TDLS_SETUP_CONFIRM == action_code) {
  724. qdf_mem_copy(set_responder.peer_mac, peer_mac,
  725. QDF_MAC_ADDR_SIZE);
  726. set_responder.vdev = vdev;
  727. if (TDLS_SETUP_RESPONSE == action_code)
  728. set_responder.responder = false;
  729. if (TDLS_SETUP_CONFIRM == action_code)
  730. set_responder.responder = true;
  731. ucfg_tdls_responder(&set_responder);
  732. }
  733. error_mgmt_req:
  734. return status;
  735. }
  736. int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode)
  737. {
  738. struct vdev_osif_priv *osif_priv;
  739. struct osif_tdls_vdev *tdls_priv;
  740. int ret;
  741. unsigned long rc;
  742. if (!vdev) {
  743. osif_err("vdev is NULL");
  744. return -EAGAIN;
  745. }
  746. osif_priv = wlan_vdev_get_ospriv(vdev);
  747. if (!osif_priv || !osif_priv->osif_tdls) {
  748. osif_err("osif priv or tdls priv is NULL");
  749. ret = -EINVAL;
  750. goto error;
  751. }
  752. tdls_priv = osif_priv->osif_tdls;
  753. reinit_completion(&tdls_priv->tdls_antenna_switch_comp);
  754. ret = ucfg_tdls_antenna_switch(vdev, mode);
  755. if (QDF_IS_STATUS_ERROR(ret)) {
  756. osif_err("ucfg_tdls_antenna_switch failed err %d", ret);
  757. ret = -EAGAIN;
  758. goto error;
  759. }
  760. rc = wait_for_completion_timeout(
  761. &tdls_priv->tdls_antenna_switch_comp,
  762. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_ANTENNA_SWITCH));
  763. if (!rc) {
  764. osif_err("timeout for tdls antenna switch %ld", rc);
  765. ret = -EAGAIN;
  766. goto error;
  767. }
  768. ret = tdls_priv->tdls_antenna_switch_status;
  769. osif_debug("tdls antenna switch status:%d", ret);
  770. error:
  771. return ret;
  772. }
  773. static void
  774. wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
  775. {
  776. struct vdev_osif_priv *osif_vdev;
  777. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  778. osif_debug("Implicit TDLS, request Send Discovery request");
  779. cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
  780. ind->peer_mac, NL80211_TDLS_DISCOVERY_REQ,
  781. false, GFP_KERNEL);
  782. }
  783. static void
  784. wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication *ind)
  785. {
  786. struct vdev_osif_priv *osif_vdev;
  787. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  788. osif_debug("Indication to request TDLS setup");
  789. cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
  790. ind->peer_mac, NL80211_TDLS_SETUP, false,
  791. GFP_KERNEL);
  792. }
  793. static void
  794. wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication *ind)
  795. {
  796. struct vdev_osif_priv *osif_vdev;
  797. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  798. osif_debug("Teardown reason %d", ind->reason);
  799. cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
  800. ind->peer_mac, NL80211_TDLS_TEARDOWN,
  801. ind->reason, GFP_KERNEL);
  802. }
  803. void wlan_cfg80211_tdls_event_callback(void *user_data,
  804. enum tdls_event_type type,
  805. struct tdls_osif_indication *ind)
  806. {
  807. struct vdev_osif_priv *osif_vdev;
  808. struct osif_tdls_vdev *tdls_priv;
  809. if (!ind || !ind->vdev) {
  810. osif_err("ind: %pK", ind);
  811. return;
  812. }
  813. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  814. if (!osif_vdev || !osif_vdev->osif_tdls) {
  815. osif_err("osif priv or tdls priv is NULL");
  816. return;
  817. }
  818. tdls_priv = osif_vdev->osif_tdls;
  819. switch (type) {
  820. case TDLS_EVENT_MGMT_TX_ACK_CNF:
  821. tdls_priv->mgmt_tx_completion_status = ind->status;
  822. complete(&tdls_priv->tdls_mgmt_comp);
  823. break;
  824. case TDLS_EVENT_ADD_PEER:
  825. tdls_priv->tdls_add_peer_status = ind->status;
  826. complete(&tdls_priv->tdls_add_peer_comp);
  827. break;
  828. case TDLS_EVENT_DEL_PEER:
  829. complete(&tdls_priv->tdls_del_peer_comp);
  830. break;
  831. case TDLS_EVENT_DISCOVERY_REQ:
  832. wlan_cfg80211_tdls_indicate_discovery(ind);
  833. break;
  834. case TDLS_EVENT_TEARDOWN_REQ:
  835. wlan_cfg80211_tdls_indicate_teardown(ind);
  836. break;
  837. case TDLS_EVENT_SETUP_REQ:
  838. wlan_cfg80211_tdls_indicate_setup(ind);
  839. break;
  840. case TDLS_EVENT_TEARDOWN_LINKS_DONE:
  841. complete(&tdls_priv->tdls_teardown_comp);
  842. break;
  843. case TDLS_EVENT_USER_CMD:
  844. tdls_priv->tdls_user_cmd_len = ind->status;
  845. complete(&tdls_priv->tdls_user_cmd_comp);
  846. break;
  847. case TDLS_EVENT_ANTENNA_SWITCH:
  848. tdls_priv->tdls_antenna_switch_status = ind->status;
  849. complete(&tdls_priv->tdls_antenna_switch_comp);
  850. default:
  851. break;
  852. }
  853. }