wlan_cfg80211_tdls.c 27 KB

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