wlan_cfg80211_tdls.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. /*
  2. * Copyright (c) 2017-2020 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. #include "wlan_cfg80211_mc_cp_stats.h"
  35. #include "sir_api.h"
  36. #define TDLS_MAX_NO_OF_2_4_CHANNELS 14
  37. static int wlan_cfg80211_tdls_validate_mac_addr(const uint8_t *mac)
  38. {
  39. static const uint8_t temp_mac[QDF_MAC_ADDR_SIZE] = {0};
  40. if (!qdf_mem_cmp(mac, temp_mac, QDF_MAC_ADDR_SIZE)) {
  41. osif_debug("Invalid Mac address " QDF_MAC_ADDR_STR
  42. " cmd declined.",
  43. QDF_MAC_ADDR_ARRAY(mac));
  44. return -EINVAL;
  45. }
  46. return 0;
  47. }
  48. QDF_STATUS wlan_cfg80211_tdls_osif_priv_init(struct wlan_objmgr_vdev *vdev)
  49. {
  50. struct osif_tdls_vdev *tdls_priv;
  51. struct vdev_osif_priv *osif_priv;
  52. osif_priv = wlan_vdev_get_ospriv(vdev);
  53. if (!osif_priv) {
  54. osif_err("osif_priv is NULL!");
  55. return QDF_STATUS_E_FAULT;
  56. }
  57. osif_debug("initialize tdls os if layer private structure");
  58. tdls_priv = qdf_mem_malloc(sizeof(*tdls_priv));
  59. if (!tdls_priv) {
  60. osif_err("failed to allocate memory for tdls_priv");
  61. return QDF_STATUS_E_NOMEM;
  62. }
  63. init_completion(&tdls_priv->tdls_add_peer_comp);
  64. init_completion(&tdls_priv->tdls_del_peer_comp);
  65. init_completion(&tdls_priv->tdls_mgmt_comp);
  66. init_completion(&tdls_priv->tdls_link_establish_req_comp);
  67. init_completion(&tdls_priv->tdls_teardown_comp);
  68. init_completion(&tdls_priv->tdls_user_cmd_comp);
  69. init_completion(&tdls_priv->tdls_antenna_switch_comp);
  70. osif_priv->osif_tdls = tdls_priv;
  71. return QDF_STATUS_SUCCESS;
  72. }
  73. void wlan_cfg80211_tdls_osif_priv_deinit(struct wlan_objmgr_vdev *vdev)
  74. {
  75. struct vdev_osif_priv *osif_priv;
  76. osif_priv = wlan_vdev_get_ospriv(vdev);
  77. if (!osif_priv) {
  78. osif_err("osif_priv is NULL!");
  79. return;
  80. }
  81. osif_debug("deinitialize tdls os if layer private structure");
  82. if (osif_priv->osif_tdls)
  83. qdf_mem_free(osif_priv->osif_tdls);
  84. osif_priv->osif_tdls = NULL;
  85. }
  86. void hdd_notify_teardown_tdls_links(struct wlan_objmgr_psoc *psoc)
  87. {
  88. struct vdev_osif_priv *osif_priv;
  89. struct osif_tdls_vdev *tdls_priv;
  90. QDF_STATUS status;
  91. unsigned long rc;
  92. struct wlan_objmgr_vdev *vdev;
  93. vdev = ucfg_get_tdls_vdev(psoc, WLAN_OSIF_ID);
  94. if (!vdev)
  95. return;
  96. osif_priv = wlan_vdev_get_ospriv(vdev);
  97. if (!osif_priv || !osif_priv->osif_tdls) {
  98. osif_err("osif priv or tdls priv is NULL");
  99. goto release_ref;
  100. }
  101. tdls_priv = osif_priv->osif_tdls;
  102. reinit_completion(&tdls_priv->tdls_teardown_comp);
  103. status = ucfg_tdls_teardown_links(psoc);
  104. if (QDF_IS_STATUS_ERROR(status)) {
  105. osif_err("ucfg_tdls_teardown_links failed err %d", status);
  106. goto release_ref;
  107. }
  108. osif_debug("Wait for tdls teardown completion. Timeout %u ms",
  109. WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS);
  110. rc = wait_for_completion_timeout(
  111. &tdls_priv->tdls_teardown_comp,
  112. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS));
  113. if (0 == rc) {
  114. osif_err(" Teardown Completion timed out rc: %ld", rc);
  115. goto release_ref;
  116. }
  117. osif_debug("TDLS teardown completion status %ld ", rc);
  118. release_ref:
  119. wlan_objmgr_vdev_release_ref(vdev,
  120. WLAN_OSIF_ID);
  121. }
  122. void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
  123. {
  124. ucfg_tdls_notify_reset_adapter(vdev);
  125. }
  126. void
  127. hdd_notify_sta_connect(uint8_t session_id,
  128. bool tdls_chan_swit_prohibited,
  129. bool tdls_prohibited,
  130. struct wlan_objmgr_vdev *vdev)
  131. {
  132. struct tdls_sta_notify_params notify_info = {0};
  133. QDF_STATUS status;
  134. if (!vdev) {
  135. osif_err("vdev is NULL");
  136. return;
  137. }
  138. status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
  139. if (QDF_IS_STATUS_ERROR(status)) {
  140. osif_err("can't get vdev");
  141. return;
  142. }
  143. notify_info.session_id = session_id;
  144. notify_info.vdev = vdev;
  145. notify_info.tdls_chan_swit_prohibited = tdls_chan_swit_prohibited;
  146. notify_info.tdls_prohibited = tdls_prohibited;
  147. ucfg_tdls_notify_sta_connect(&notify_info);
  148. }
  149. void hdd_notify_sta_disconnect(uint8_t session_id,
  150. bool lfr_roam,
  151. bool user_disconnect,
  152. struct wlan_objmgr_vdev *vdev)
  153. {
  154. struct tdls_sta_notify_params notify_info = {0};
  155. QDF_STATUS status;
  156. if (!vdev) {
  157. osif_err("vdev is NULL");
  158. return;
  159. }
  160. status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
  161. if (QDF_IS_STATUS_ERROR(status)) {
  162. osif_err("can't get vdev");
  163. return;
  164. }
  165. notify_info.session_id = session_id;
  166. notify_info.lfr_roam = lfr_roam;
  167. notify_info.tdls_chan_swit_prohibited = false;
  168. notify_info.tdls_prohibited = false;
  169. notify_info.vdev = vdev;
  170. notify_info.user_disconnect = user_disconnect;
  171. ucfg_tdls_notify_sta_disconnect(&notify_info);
  172. }
  173. int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
  174. const uint8_t *mac)
  175. {
  176. struct tdls_add_peer_params *add_peer_req;
  177. int status;
  178. struct vdev_osif_priv *osif_priv;
  179. struct osif_tdls_vdev *tdls_priv;
  180. unsigned long rc;
  181. status = wlan_cfg80211_tdls_validate_mac_addr(mac);
  182. if (status)
  183. return status;
  184. osif_debug("Add TDLS peer " QDF_MAC_ADDR_STR,
  185. QDF_MAC_ADDR_ARRAY(mac));
  186. add_peer_req = qdf_mem_malloc(sizeof(*add_peer_req));
  187. if (!add_peer_req) {
  188. osif_err("Failed to allocate tdls add peer request mem");
  189. return -EINVAL;
  190. }
  191. osif_priv = wlan_vdev_get_ospriv(vdev);
  192. if (!osif_priv || !osif_priv->osif_tdls) {
  193. osif_err("osif_tdls_vdev or osif_priv is NULL for the current vdev");
  194. status = -EINVAL;
  195. goto error;
  196. }
  197. tdls_priv = osif_priv->osif_tdls;
  198. add_peer_req->vdev_id = wlan_vdev_get_id(vdev);
  199. qdf_mem_copy(add_peer_req->peer_addr, mac, QDF_MAC_ADDR_SIZE);
  200. reinit_completion(&tdls_priv->tdls_add_peer_comp);
  201. status = ucfg_tdls_add_peer(vdev, add_peer_req);
  202. if (QDF_IS_STATUS_ERROR(status)) {
  203. osif_err("ucfg_tdls_add_peer returned err %d", status);
  204. status = -EIO;
  205. goto error;
  206. }
  207. rc = wait_for_completion_timeout(
  208. &tdls_priv->tdls_add_peer_comp,
  209. msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
  210. if (!rc) {
  211. osif_err("timeout for tdls add peer indication %ld", rc);
  212. status = -EPERM;
  213. goto error;
  214. }
  215. if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
  216. osif_err("tdls add peer failed, status:%d",
  217. tdls_priv->tdls_add_peer_status);
  218. status = -EPERM;
  219. }
  220. error:
  221. qdf_mem_free(add_peer_req);
  222. return status;
  223. }
  224. static bool
  225. is_duplicate_channel(uint8_t *arr, int index, uint8_t match)
  226. {
  227. int i;
  228. for (i = 0; i < index; i++) {
  229. if (arr[i] == match)
  230. return true;
  231. }
  232. return false;
  233. }
  234. static void
  235. tdls_calc_channels_from_staparams(struct tdls_update_peer_params *req_info,
  236. struct station_parameters *params)
  237. {
  238. int i = 0, j = 0, k = 0, no_of_channels = 0;
  239. int num_unique_channels;
  240. int next;
  241. uint8_t *dest_chans;
  242. const uint8_t *src_chans;
  243. dest_chans = req_info->supported_channels;
  244. src_chans = params->supported_channels;
  245. /* Convert (first channel , number of channels) tuple to
  246. * the total list of channels. This goes with the assumption
  247. * that if the first channel is < 14, then the next channels
  248. * are an incremental of 1 else an incremental of 4 till the number
  249. * of channels.
  250. */
  251. for (i = 0; i < params->supported_channels_len &&
  252. j < WLAN_MAC_MAX_SUPP_CHANNELS; i += 2) {
  253. int wifi_chan_index;
  254. if (!is_duplicate_channel(dest_chans, j, src_chans[i]))
  255. dest_chans[j] = src_chans[i];
  256. else
  257. continue;
  258. wifi_chan_index = ((dest_chans[j] <= WLAN_CHANNEL_14) ? 1 : 4);
  259. no_of_channels = src_chans[i + 1];
  260. osif_debug("i:%d,j:%d,k:%d,[%d]:%d,index:%d,chans_num: %d",
  261. i, j, k, j,
  262. dest_chans[j],
  263. wifi_chan_index,
  264. no_of_channels);
  265. for (k = 1; k <= no_of_channels &&
  266. j < WLAN_MAC_MAX_SUPP_CHANNELS - 1; k++) {
  267. next = dest_chans[j] + wifi_chan_index;
  268. if (!is_duplicate_channel(dest_chans, j + 1, next))
  269. dest_chans[j + 1] = next;
  270. else
  271. continue;
  272. osif_debug("i: %d, j: %d, k: %d, [%d]: %d",
  273. i, j, k, j + 1, dest_chans[j + 1]);
  274. j += 1;
  275. }
  276. }
  277. num_unique_channels = j + 1;
  278. osif_debug("Unique Channel List: supported_channels ");
  279. for (i = 0; i < num_unique_channels; i++)
  280. osif_debug("[%d]: %d,", i, dest_chans[i]);
  281. if (num_unique_channels > NUM_CHANNELS)
  282. num_unique_channels = NUM_CHANNELS;
  283. req_info->supported_channels_len = num_unique_channels;
  284. osif_debug("After removing duplcates supported_channels_len: %d",
  285. req_info->supported_channels_len);
  286. }
  287. static void
  288. wlan_cfg80211_tdls_extract_params(struct tdls_update_peer_params *req_info,
  289. struct station_parameters *params)
  290. {
  291. int i;
  292. osif_debug("sta cap %d, uapsd_queue %d, max_sp %d",
  293. params->capability,
  294. params->uapsd_queues, params->max_sp);
  295. if (!req_info) {
  296. osif_err("reg_info is NULL");
  297. return;
  298. }
  299. req_info->capability = params->capability;
  300. req_info->uapsd_queues = params->uapsd_queues;
  301. req_info->max_sp = params->max_sp;
  302. if (params->supported_channels_len)
  303. tdls_calc_channels_from_staparams(req_info, params);
  304. if (params->supported_oper_classes_len > WLAN_MAX_SUPP_OPER_CLASSES) {
  305. osif_debug("received oper classes:%d, resetting it to max supported: %d",
  306. params->supported_oper_classes_len,
  307. WLAN_MAX_SUPP_OPER_CLASSES);
  308. params->supported_oper_classes_len = WLAN_MAX_SUPP_OPER_CLASSES;
  309. }
  310. qdf_mem_copy(req_info->supported_oper_classes,
  311. params->supported_oper_classes,
  312. params->supported_oper_classes_len);
  313. req_info->supported_oper_classes_len =
  314. params->supported_oper_classes_len;
  315. if (params->ext_capab_len)
  316. qdf_mem_copy(req_info->extn_capability, params->ext_capab,
  317. sizeof(req_info->extn_capability));
  318. if (params->ht_capa) {
  319. req_info->htcap_present = 1;
  320. qdf_mem_copy(&req_info->ht_cap, params->ht_capa,
  321. sizeof(struct htcap_cmn_ie));
  322. }
  323. req_info->supported_rates_len = params->supported_rates_len;
  324. /* Note : The Maximum sizeof supported_rates sent by the Supplicant is
  325. * 32. The supported_rates array , for all the structures propogating
  326. * till Add Sta to the firmware has to be modified , if the supplicant
  327. * (ieee80211) is modified to send more rates.
  328. */
  329. /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
  330. */
  331. if (req_info->supported_rates_len > WLAN_MAC_MAX_SUPP_RATES)
  332. req_info->supported_rates_len = WLAN_MAC_MAX_SUPP_RATES;
  333. if (req_info->supported_rates_len) {
  334. qdf_mem_copy(req_info->supported_rates,
  335. params->supported_rates,
  336. req_info->supported_rates_len);
  337. osif_debug("Supported Rates with Length %d",
  338. req_info->supported_rates_len);
  339. for (i = 0; i < req_info->supported_rates_len; i++)
  340. osif_debug("[%d]: %0x", i,
  341. req_info->supported_rates[i]);
  342. }
  343. if (params->vht_capa) {
  344. req_info->vhtcap_present = 1;
  345. qdf_mem_copy(&req_info->vht_cap, params->vht_capa,
  346. sizeof(struct vhtcap));
  347. }
  348. if (params->ht_capa || params->vht_capa ||
  349. (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
  350. req_info->is_qos_wmm_sta = true;
  351. if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) {
  352. osif_debug("TDLS peer pmf capable");
  353. req_info->is_pmf = 1;
  354. }
  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. psoc = user_data;
  536. if (!psoc) {
  537. osif_err("psoc is null");
  538. return;
  539. }
  540. vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
  541. rx_frame->vdev_id, WLAN_TDLS_NB_ID);
  542. if (!vdev) {
  543. osif_err("vdev is null");
  544. return;
  545. }
  546. osif_priv = wlan_vdev_get_ospriv(vdev);
  547. if (!osif_priv) {
  548. osif_err("osif_priv is null");
  549. goto fail;
  550. }
  551. wdev = osif_priv->wdev;
  552. if (!wdev) {
  553. osif_err("wdev is null");
  554. goto fail;
  555. }
  556. osif_notice("Indicate frame over nl80211, vdev id:%d, idx:%d",
  557. rx_frame->vdev_id, wdev->netdev->ifindex);
  558. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  559. cfg80211_rx_mgmt(wdev, rx_frame->rx_freq, rx_frame->rx_rssi * 100,
  560. rx_frame->buf, rx_frame->frame_len,
  561. NL80211_RXMGMT_FLAG_ANSWERED);
  562. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  563. cfg80211_rx_mgmt(wdev, rx_frame->rx_freq, rx_frame->rx_rssi * 100,
  564. rx_frame->buf, rx_frame->frame_len,
  565. NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
  566. #else
  567. cfg80211_rx_mgmt(wdev, rx_frame->rx_freq, rx_frame->rx_rssi * 100,
  568. rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC);
  569. #endif /* LINUX_VERSION_CODE */
  570. fail:
  571. wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
  572. }
  573. static void wlan_cfg80211_update_tdls_peers_rssi(struct wlan_objmgr_vdev *vdev)
  574. {
  575. int ret = 0, i;
  576. struct stats_event *rssi_info;
  577. struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
  578. rssi_info = wlan_cfg80211_mc_cp_stats_get_peer_rssi(
  579. vdev, bcast_mac.bytes,
  580. &ret);
  581. if (ret || !rssi_info) {
  582. osif_err("get peer rssi fail");
  583. wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info);
  584. return;
  585. }
  586. for (i = 0; i < rssi_info->num_peer_stats; i++)
  587. ucfg_tdls_set_rssi(vdev, rssi_info->peer_stats[i].peer_macaddr,
  588. rssi_info->peer_stats[i].peer_rssi);
  589. wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info);
  590. }
  591. int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
  592. char *buf, int buflen)
  593. {
  594. struct vdev_osif_priv *osif_priv;
  595. struct osif_tdls_vdev *tdls_priv;
  596. int32_t len;
  597. QDF_STATUS status;
  598. unsigned long rc;
  599. osif_priv = wlan_vdev_get_ospriv(vdev);
  600. if (!osif_priv || !osif_priv->osif_tdls) {
  601. osif_err("osif_tdls_vdev or osif_priv is NULL for the current vdev");
  602. return -EINVAL;
  603. }
  604. tdls_priv = osif_priv->osif_tdls;
  605. wlan_cfg80211_update_tdls_peers_rssi(vdev);
  606. reinit_completion(&tdls_priv->tdls_user_cmd_comp);
  607. status = ucfg_tdls_get_all_peers(vdev, buf, buflen);
  608. if (QDF_IS_STATUS_ERROR(status)) {
  609. osif_err("ucfg_tdls_get_all_peers failed err %d", status);
  610. len = scnprintf(buf, buflen,
  611. "\nucfg_tdls_send_mgmt failed\n");
  612. goto error_get_tdls_peers;
  613. }
  614. osif_debug("Wait for tdls_user_cmd_comp. Timeout %u ms",
  615. WAIT_TIME_FOR_TDLS_USER_CMD);
  616. rc = wait_for_completion_timeout(
  617. &tdls_priv->tdls_user_cmd_comp,
  618. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_USER_CMD));
  619. if (0 == rc) {
  620. osif_err("TDLS user cmd get all peers timed out rc %ld",
  621. rc);
  622. len = scnprintf(buf, buflen,
  623. "\nTDLS user cmd get all peers timed out\n");
  624. goto error_get_tdls_peers;
  625. }
  626. len = tdls_priv->tdls_user_cmd_len;
  627. error_get_tdls_peers:
  628. return len;
  629. }
  630. int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
  631. const uint8_t *peer_mac,
  632. uint8_t action_code, uint8_t dialog_token,
  633. uint16_t status_code, uint32_t peer_capability,
  634. const uint8_t *buf, size_t len)
  635. {
  636. struct tdls_action_frame_request mgmt_req;
  637. struct vdev_osif_priv *osif_priv;
  638. struct osif_tdls_vdev *tdls_priv;
  639. int status;
  640. unsigned long rc;
  641. struct tdls_set_responder_req set_responder;
  642. status = wlan_cfg80211_tdls_validate_mac_addr(peer_mac);
  643. if (status)
  644. return status;
  645. osif_priv = wlan_vdev_get_ospriv(vdev);
  646. if (!osif_priv || !osif_priv->osif_tdls) {
  647. osif_err("osif priv or tdls priv is NULL");
  648. return -EINVAL;
  649. }
  650. tdls_priv = osif_priv->osif_tdls;
  651. /* make sure doesn't call send_mgmt() while it is pending */
  652. if (TDLS_VDEV_MAGIC == tdls_priv->mgmt_tx_completion_status) {
  653. osif_err(QDF_MAC_ADDR_STR " action %d couldn't sent, as one is pending. return EBUSY",
  654. QDF_MAC_ADDR_ARRAY(peer_mac), action_code);
  655. return -EBUSY;
  656. }
  657. /* Reset TDLS VDEV magic */
  658. tdls_priv->mgmt_tx_completion_status = TDLS_VDEV_MAGIC;
  659. /*prepare the request */
  660. /* Validate the management Request */
  661. mgmt_req.chk_frame.action_code = action_code;
  662. qdf_mem_copy(mgmt_req.chk_frame.peer_mac, peer_mac, QDF_MAC_ADDR_SIZE);
  663. mgmt_req.chk_frame.dialog_token = dialog_token;
  664. mgmt_req.chk_frame.action_code = action_code;
  665. mgmt_req.chk_frame.status_code = status_code;
  666. mgmt_req.chk_frame.len = len;
  667. mgmt_req.vdev = vdev;
  668. mgmt_req.vdev_id = wlan_vdev_get_id(vdev);
  669. mgmt_req.session_id = mgmt_req.vdev_id;
  670. /* populate management req params */
  671. qdf_mem_copy(mgmt_req.tdls_mgmt.peer_mac.bytes,
  672. peer_mac, QDF_MAC_ADDR_SIZE);
  673. mgmt_req.tdls_mgmt.dialog = dialog_token;
  674. mgmt_req.tdls_mgmt.frame_type = action_code;
  675. mgmt_req.tdls_mgmt.len = len;
  676. mgmt_req.tdls_mgmt.peer_capability = peer_capability;
  677. mgmt_req.tdls_mgmt.status_code = mgmt_req.chk_frame.status_code;
  678. /*populate the additional IE's */
  679. mgmt_req.cmd_buf = buf;
  680. mgmt_req.len = len;
  681. reinit_completion(&tdls_priv->tdls_mgmt_comp);
  682. status = ucfg_tdls_send_mgmt_frame(&mgmt_req);
  683. if (QDF_IS_STATUS_ERROR(status)) {
  684. osif_err("ucfg_tdls_send_mgmt failed err %d", status);
  685. status = -EIO;
  686. tdls_priv->mgmt_tx_completion_status = false;
  687. goto error_mgmt_req;
  688. }
  689. osif_debug("Wait for tdls_mgmt_comp. Timeout %u ms",
  690. WAIT_TIME_FOR_TDLS_MGMT);
  691. rc = wait_for_completion_timeout(
  692. &tdls_priv->tdls_mgmt_comp,
  693. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_MGMT));
  694. if ((0 == rc) || (QDF_STATUS_SUCCESS !=
  695. tdls_priv->mgmt_tx_completion_status)) {
  696. osif_err("%s rc %ld mgmtTxCompletionStatus %u",
  697. !rc ? "Mgmt Tx Completion timed out" :
  698. "Mgmt Tx Completion failed",
  699. rc, tdls_priv->mgmt_tx_completion_status);
  700. tdls_priv->mgmt_tx_completion_status = false;
  701. status = -EINVAL;
  702. goto error_mgmt_req;
  703. }
  704. osif_debug("Mgmt Tx Completion status %ld TxCompletion %u",
  705. rc, tdls_priv->mgmt_tx_completion_status);
  706. if (TDLS_SETUP_RESPONSE == action_code ||
  707. TDLS_SETUP_CONFIRM == action_code) {
  708. qdf_mem_copy(set_responder.peer_mac, peer_mac,
  709. QDF_MAC_ADDR_SIZE);
  710. set_responder.vdev = vdev;
  711. if (TDLS_SETUP_RESPONSE == action_code)
  712. set_responder.responder = false;
  713. if (TDLS_SETUP_CONFIRM == action_code)
  714. set_responder.responder = true;
  715. ucfg_tdls_responder(&set_responder);
  716. }
  717. error_mgmt_req:
  718. return status;
  719. }
  720. int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode)
  721. {
  722. struct vdev_osif_priv *osif_priv;
  723. struct osif_tdls_vdev *tdls_priv;
  724. int ret;
  725. unsigned long rc;
  726. if (!vdev) {
  727. osif_err("vdev is NULL");
  728. return -EAGAIN;
  729. }
  730. osif_priv = wlan_vdev_get_ospriv(vdev);
  731. if (!osif_priv || !osif_priv->osif_tdls) {
  732. osif_err("osif priv or tdls priv is NULL");
  733. ret = -EINVAL;
  734. goto error;
  735. }
  736. tdls_priv = osif_priv->osif_tdls;
  737. reinit_completion(&tdls_priv->tdls_antenna_switch_comp);
  738. ret = ucfg_tdls_antenna_switch(vdev, mode);
  739. if (QDF_IS_STATUS_ERROR(ret)) {
  740. osif_err("ucfg_tdls_antenna_switch failed err %d", ret);
  741. ret = -EAGAIN;
  742. goto error;
  743. }
  744. rc = wait_for_completion_timeout(
  745. &tdls_priv->tdls_antenna_switch_comp,
  746. msecs_to_jiffies(WAIT_TIME_FOR_TDLS_ANTENNA_SWITCH));
  747. if (!rc) {
  748. osif_err("timeout for tdls antenna switch %ld", rc);
  749. ret = -EAGAIN;
  750. goto error;
  751. }
  752. ret = tdls_priv->tdls_antenna_switch_status;
  753. osif_debug("tdls antenna switch status:%d", ret);
  754. error:
  755. return ret;
  756. }
  757. static void
  758. wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
  759. {
  760. struct vdev_osif_priv *osif_vdev;
  761. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  762. cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
  763. ind->peer_mac, NL80211_TDLS_DISCOVERY_REQ,
  764. false, GFP_KERNEL);
  765. }
  766. static void
  767. wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication *ind)
  768. {
  769. struct vdev_osif_priv *osif_vdev;
  770. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  771. osif_debug("Indication to request TDLS setup");
  772. cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
  773. ind->peer_mac, NL80211_TDLS_SETUP, false,
  774. GFP_KERNEL);
  775. }
  776. static void
  777. wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication *ind)
  778. {
  779. struct vdev_osif_priv *osif_vdev;
  780. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  781. osif_debug("Teardown reason %d", ind->reason);
  782. cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
  783. ind->peer_mac, NL80211_TDLS_TEARDOWN,
  784. ind->reason, GFP_KERNEL);
  785. }
  786. void wlan_cfg80211_tdls_event_callback(void *user_data,
  787. enum tdls_event_type type,
  788. struct tdls_osif_indication *ind)
  789. {
  790. struct vdev_osif_priv *osif_vdev;
  791. struct osif_tdls_vdev *tdls_priv;
  792. if (!ind || !ind->vdev) {
  793. osif_err("ind: %pK", ind);
  794. return;
  795. }
  796. osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
  797. if (!osif_vdev || !osif_vdev->osif_tdls) {
  798. osif_err("osif priv or tdls priv is NULL");
  799. return;
  800. }
  801. tdls_priv = osif_vdev->osif_tdls;
  802. switch (type) {
  803. case TDLS_EVENT_MGMT_TX_ACK_CNF:
  804. tdls_priv->mgmt_tx_completion_status = ind->status;
  805. complete(&tdls_priv->tdls_mgmt_comp);
  806. break;
  807. case TDLS_EVENT_ADD_PEER:
  808. tdls_priv->tdls_add_peer_status = ind->status;
  809. complete(&tdls_priv->tdls_add_peer_comp);
  810. break;
  811. case TDLS_EVENT_DEL_PEER:
  812. complete(&tdls_priv->tdls_del_peer_comp);
  813. break;
  814. case TDLS_EVENT_DISCOVERY_REQ:
  815. wlan_cfg80211_tdls_indicate_discovery(ind);
  816. break;
  817. case TDLS_EVENT_TEARDOWN_REQ:
  818. wlan_cfg80211_tdls_indicate_teardown(ind);
  819. break;
  820. case TDLS_EVENT_SETUP_REQ:
  821. wlan_cfg80211_tdls_indicate_setup(ind);
  822. break;
  823. case TDLS_EVENT_TEARDOWN_LINKS_DONE:
  824. complete(&tdls_priv->tdls_teardown_comp);
  825. break;
  826. case TDLS_EVENT_USER_CMD:
  827. tdls_priv->tdls_user_cmd_len = ind->status;
  828. complete(&tdls_priv->tdls_user_cmd_comp);
  829. break;
  830. case TDLS_EVENT_ANTENNA_SWITCH:
  831. tdls_priv->tdls_antenna_switch_status = ind->status;
  832. complete(&tdls_priv->tdls_antenna_switch_comp);
  833. default:
  834. break;
  835. }
  836. }