tdls.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /******************************************************************************
  2. *
  3. * This file is provided under a dual BSD/GPLv2 license. When using or
  4. * redistributing this file, you may do so under either license.
  5. *
  6. * GPL LICENSE SUMMARY
  7. *
  8. * Copyright(c) 2014 Intel Mobile Communications GmbH
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of version 2 of the GNU General Public License as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  22. * USA
  23. *
  24. * The full GNU General Public License is included in this distribution
  25. * in the file called COPYING.
  26. *
  27. * Contact Information:
  28. * Intel Linux Wireless <ilw@linux.intel.com>
  29. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30. *
  31. * BSD LICENSE
  32. *
  33. * Copyright(c) 2014 Intel Mobile Communications GmbH
  34. * All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. *
  40. * * Redistributions of source code must retain the above copyright
  41. * notice, this list of conditions and the following disclaimer.
  42. * * Redistributions in binary form must reproduce the above copyright
  43. * notice, this list of conditions and the following disclaimer in
  44. * the documentation and/or other materials provided with the
  45. * distribution.
  46. * * Neither the name Intel Corporation nor the names of its
  47. * contributors may be used to endorse or promote products derived
  48. * from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  54. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  55. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  56. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  57. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  58. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  59. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  60. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61. *
  62. *****************************************************************************/
  63. #include <linux/etherdevice.h>
  64. #include "mvm.h"
  65. #include "time-event.h"
  66. #define TU_TO_US(x) (x * 1024)
  67. #define TU_TO_MS(x) (TU_TO_US(x) / 1000)
  68. void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
  69. {
  70. struct ieee80211_sta *sta;
  71. struct iwl_mvm_sta *mvmsta;
  72. int i;
  73. lockdep_assert_held(&mvm->mutex);
  74. for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
  75. sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
  76. lockdep_is_held(&mvm->mutex));
  77. if (!sta || IS_ERR(sta) || !sta->tdls)
  78. continue;
  79. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  80. ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
  81. NL80211_TDLS_TEARDOWN,
  82. WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
  83. GFP_KERNEL);
  84. }
  85. }
  86. int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
  87. {
  88. struct ieee80211_sta *sta;
  89. struct iwl_mvm_sta *mvmsta;
  90. int count = 0;
  91. int i;
  92. lockdep_assert_held(&mvm->mutex);
  93. for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
  94. sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
  95. lockdep_is_held(&mvm->mutex));
  96. if (!sta || IS_ERR(sta) || !sta->tdls)
  97. continue;
  98. if (vif) {
  99. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  100. if (mvmsta->vif != vif)
  101. continue;
  102. }
  103. count++;
  104. }
  105. return count;
  106. }
  107. static void iwl_mvm_tdls_config(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
  108. {
  109. struct iwl_rx_packet *pkt;
  110. struct iwl_tdls_config_res *resp;
  111. struct iwl_tdls_config_cmd tdls_cfg_cmd = {};
  112. struct iwl_host_cmd cmd = {
  113. .id = TDLS_CONFIG_CMD,
  114. .flags = CMD_WANT_SKB,
  115. .data = { &tdls_cfg_cmd, },
  116. .len = { sizeof(struct iwl_tdls_config_cmd), },
  117. };
  118. struct ieee80211_sta *sta;
  119. int ret, i, cnt;
  120. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  121. lockdep_assert_held(&mvm->mutex);
  122. tdls_cfg_cmd.id_and_color =
  123. cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
  124. tdls_cfg_cmd.tx_to_ap_tid = IWL_MVM_TDLS_FW_TID;
  125. tdls_cfg_cmd.tx_to_ap_ssn = cpu_to_le16(0); /* not used for now */
  126. /* for now the Tx cmd is empty and unused */
  127. /* populate TDLS peer data */
  128. cnt = 0;
  129. for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
  130. sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
  131. lockdep_is_held(&mvm->mutex));
  132. if (IS_ERR_OR_NULL(sta) || !sta->tdls)
  133. continue;
  134. tdls_cfg_cmd.sta_info[cnt].sta_id = i;
  135. tdls_cfg_cmd.sta_info[cnt].tx_to_peer_tid =
  136. IWL_MVM_TDLS_FW_TID;
  137. tdls_cfg_cmd.sta_info[cnt].tx_to_peer_ssn = cpu_to_le16(0);
  138. tdls_cfg_cmd.sta_info[cnt].is_initiator =
  139. cpu_to_le32(sta->tdls_initiator ? 1 : 0);
  140. cnt++;
  141. }
  142. tdls_cfg_cmd.tdls_peer_count = cnt;
  143. IWL_DEBUG_TDLS(mvm, "send TDLS config to FW for %d peers\n", cnt);
  144. ret = iwl_mvm_send_cmd(mvm, &cmd);
  145. if (WARN_ON_ONCE(ret))
  146. return;
  147. pkt = cmd.resp_pkt;
  148. if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
  149. IWL_ERR(mvm, "Bad return from TDLS_CONFIG_COMMAND (0x%08X)\n",
  150. pkt->hdr.flags);
  151. goto exit;
  152. }
  153. if (WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) != sizeof(*resp)))
  154. goto exit;
  155. /* we don't really care about the response at this point */
  156. exit:
  157. iwl_free_resp(&cmd);
  158. }
  159. void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
  160. bool sta_added)
  161. {
  162. int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
  163. /* when the first peer joins, send a power update first */
  164. if (tdls_sta_cnt == 1 && sta_added)
  165. iwl_mvm_power_update_mac(mvm);
  166. /* configure the FW with TDLS peer info */
  167. iwl_mvm_tdls_config(mvm, vif);
  168. /* when the last peer leaves, send a power update last */
  169. if (tdls_sta_cnt == 0 && !sta_added)
  170. iwl_mvm_power_update_mac(mvm);
  171. }
  172. void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
  173. struct ieee80211_vif *vif)
  174. {
  175. struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
  176. u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
  177. /*
  178. * iwl_mvm_protect_session() reads directly from the device
  179. * (the system time), so make sure it is available.
  180. */
  181. if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
  182. return;
  183. mutex_lock(&mvm->mutex);
  184. /* Protect the session to hear the TDLS setup response on the channel */
  185. iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
  186. mutex_unlock(&mvm->mutex);
  187. iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
  188. }
  189. static const char *
  190. iwl_mvm_tdls_cs_state_str(enum iwl_mvm_tdls_cs_state state)
  191. {
  192. switch (state) {
  193. case IWL_MVM_TDLS_SW_IDLE:
  194. return "IDLE";
  195. case IWL_MVM_TDLS_SW_REQ_SENT:
  196. return "REQ SENT";
  197. case IWL_MVM_TDLS_SW_REQ_RCVD:
  198. return "REQ RECEIVED";
  199. case IWL_MVM_TDLS_SW_ACTIVE:
  200. return "ACTIVE";
  201. }
  202. return NULL;
  203. }
  204. static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm,
  205. enum iwl_mvm_tdls_cs_state state)
  206. {
  207. if (mvm->tdls_cs.state == state)
  208. return;
  209. IWL_DEBUG_TDLS(mvm, "TDLS channel switch state: %s -> %s\n",
  210. iwl_mvm_tdls_cs_state_str(mvm->tdls_cs.state),
  211. iwl_mvm_tdls_cs_state_str(state));
  212. mvm->tdls_cs.state = state;
  213. if (state == IWL_MVM_TDLS_SW_IDLE)
  214. mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT;
  215. }
  216. int iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
  217. struct iwl_device_cmd *cmd)
  218. {
  219. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  220. struct iwl_tdls_channel_switch_notif *notif = (void *)pkt->data;
  221. struct ieee80211_sta *sta;
  222. unsigned int delay;
  223. struct iwl_mvm_sta *mvmsta;
  224. struct ieee80211_vif *vif;
  225. u32 sta_id = le32_to_cpu(notif->sta_id);
  226. lockdep_assert_held(&mvm->mutex);
  227. /* can fail sometimes */
  228. if (!le32_to_cpu(notif->status)) {
  229. iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
  230. goto out;
  231. }
  232. if (WARN_ON(sta_id >= IWL_MVM_STATION_COUNT))
  233. goto out;
  234. sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
  235. lockdep_is_held(&mvm->mutex));
  236. /* the station may not be here, but if it is, it must be a TDLS peer */
  237. if (IS_ERR_OR_NULL(sta) || WARN_ON(!sta->tdls))
  238. goto out;
  239. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  240. vif = mvmsta->vif;
  241. /*
  242. * Update state and possibly switch again after this is over (DTIM).
  243. * Also convert TU to msec.
  244. */
  245. delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
  246. mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
  247. msecs_to_jiffies(delay));
  248. iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_ACTIVE);
  249. out:
  250. return 0;
  251. }
  252. static int
  253. iwl_mvm_tdls_check_action(struct iwl_mvm *mvm,
  254. enum iwl_tdls_channel_switch_type type,
  255. const u8 *peer, bool peer_initiator)
  256. {
  257. bool same_peer = false;
  258. int ret = 0;
  259. /* get the existing peer if it's there */
  260. if (mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE &&
  261. mvm->tdls_cs.cur_sta_id != IWL_MVM_STATION_COUNT) {
  262. struct ieee80211_sta *sta = rcu_dereference_protected(
  263. mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
  264. lockdep_is_held(&mvm->mutex));
  265. if (!IS_ERR_OR_NULL(sta))
  266. same_peer = ether_addr_equal(peer, sta->addr);
  267. }
  268. switch (mvm->tdls_cs.state) {
  269. case IWL_MVM_TDLS_SW_IDLE:
  270. /*
  271. * might be spurious packet from the peer after the switch is
  272. * already done
  273. */
  274. if (type == TDLS_MOVE_CH)
  275. ret = -EINVAL;
  276. break;
  277. case IWL_MVM_TDLS_SW_REQ_SENT:
  278. /*
  279. * We received a ch-switch request while an outgoing one is
  280. * pending. Allow it to proceed if the other peer is the same
  281. * one we sent to, and we are not the link initiator.
  282. */
  283. if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH) {
  284. if (!same_peer)
  285. ret = -EBUSY;
  286. else if (!peer_initiator) /* we are the initiator */
  287. ret = -EBUSY;
  288. }
  289. break;
  290. case IWL_MVM_TDLS_SW_REQ_RCVD:
  291. /* as above, allow the link initiator to proceed */
  292. if (type == TDLS_SEND_CHAN_SW_REQ) {
  293. if (!same_peer)
  294. ret = -EBUSY;
  295. else if (peer_initiator) /* they are the initiator */
  296. ret = -EBUSY;
  297. } else if (type == TDLS_MOVE_CH) {
  298. ret = -EINVAL;
  299. }
  300. break;
  301. case IWL_MVM_TDLS_SW_ACTIVE:
  302. /* we don't allow initiations during active channel switch */
  303. if (type == TDLS_SEND_CHAN_SW_REQ)
  304. ret = -EINVAL;
  305. break;
  306. }
  307. if (ret)
  308. IWL_DEBUG_TDLS(mvm,
  309. "Invalid TDLS action %d state %d peer %pM same_peer %d initiator %d\n",
  310. type, mvm->tdls_cs.state, peer, same_peer,
  311. peer_initiator);
  312. return ret;
  313. }
  314. static int
  315. iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
  316. struct ieee80211_vif *vif,
  317. enum iwl_tdls_channel_switch_type type,
  318. const u8 *peer, bool peer_initiator,
  319. u8 oper_class,
  320. struct cfg80211_chan_def *chandef,
  321. u32 timestamp, u16 switch_time,
  322. u16 switch_timeout, struct sk_buff *skb,
  323. u32 ch_sw_tm_ie)
  324. {
  325. struct ieee80211_sta *sta;
  326. struct iwl_mvm_sta *mvmsta;
  327. struct ieee80211_tx_info *info;
  328. struct ieee80211_hdr *hdr;
  329. struct iwl_tdls_channel_switch_cmd cmd = {0};
  330. int ret;
  331. lockdep_assert_held(&mvm->mutex);
  332. ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator);
  333. if (ret)
  334. return ret;
  335. if (!skb || WARN_ON(skb->len > IWL_TDLS_CH_SW_FRAME_MAX_SIZE)) {
  336. ret = -EINVAL;
  337. goto out;
  338. }
  339. cmd.switch_type = type;
  340. cmd.timing.frame_timestamp = cpu_to_le32(timestamp);
  341. cmd.timing.switch_time = cpu_to_le32(switch_time);
  342. cmd.timing.switch_timeout = cpu_to_le32(switch_timeout);
  343. rcu_read_lock();
  344. sta = ieee80211_find_sta(vif, peer);
  345. if (!sta) {
  346. rcu_read_unlock();
  347. ret = -ENOENT;
  348. goto out;
  349. }
  350. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  351. cmd.peer_sta_id = cpu_to_le32(mvmsta->sta_id);
  352. if (!chandef) {
  353. if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
  354. mvm->tdls_cs.peer.chandef.chan) {
  355. /* actually moving to the channel */
  356. chandef = &mvm->tdls_cs.peer.chandef;
  357. } else if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_ACTIVE &&
  358. type == TDLS_MOVE_CH) {
  359. /* we need to return to base channel */
  360. struct ieee80211_chanctx_conf *chanctx =
  361. rcu_dereference(vif->chanctx_conf);
  362. if (WARN_ON_ONCE(!chanctx)) {
  363. rcu_read_unlock();
  364. goto out;
  365. }
  366. chandef = &chanctx->def;
  367. }
  368. }
  369. if (chandef) {
  370. cmd.ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
  371. PHY_BAND_24 : PHY_BAND_5);
  372. cmd.ci.channel = chandef->chan->hw_value;
  373. cmd.ci.width = iwl_mvm_get_channel_width(chandef);
  374. cmd.ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef);
  375. }
  376. /* keep quota calculation simple for now - 50% of DTIM for TDLS */
  377. cmd.timing.max_offchan_duration =
  378. cpu_to_le32(TU_TO_US(vif->bss_conf.dtim_period *
  379. vif->bss_conf.beacon_int) / 2);
  380. /* Switch time is the first element in the switch-timing IE. */
  381. cmd.frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2);
  382. info = IEEE80211_SKB_CB(skb);
  383. if (info->control.hw_key)
  384. iwl_mvm_set_tx_cmd_crypto(mvm, info, &cmd.frame.tx_cmd, skb);
  385. iwl_mvm_set_tx_cmd(mvm, skb, &cmd.frame.tx_cmd, info,
  386. mvmsta->sta_id);
  387. hdr = (void *)skb->data;
  388. iwl_mvm_set_tx_cmd_rate(mvm, &cmd.frame.tx_cmd, info, sta,
  389. hdr->frame_control);
  390. rcu_read_unlock();
  391. memcpy(cmd.frame.data, skb->data, skb->len);
  392. ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0,
  393. sizeof(cmd), &cmd);
  394. if (ret) {
  395. IWL_ERR(mvm, "Failed to send TDLS_CHANNEL_SWITCH cmd: %d\n",
  396. ret);
  397. goto out;
  398. }
  399. /* channel switch has started, update state */
  400. if (type != TDLS_MOVE_CH) {
  401. mvm->tdls_cs.cur_sta_id = mvmsta->sta_id;
  402. iwl_mvm_tdls_update_cs_state(mvm,
  403. type == TDLS_SEND_CHAN_SW_REQ ?
  404. IWL_MVM_TDLS_SW_REQ_SENT :
  405. IWL_MVM_TDLS_SW_REQ_RCVD);
  406. }
  407. out:
  408. /* channel switch failed - we are idle */
  409. if (ret)
  410. iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
  411. return ret;
  412. }
  413. void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
  414. {
  415. struct iwl_mvm *mvm;
  416. struct ieee80211_sta *sta;
  417. struct iwl_mvm_sta *mvmsta;
  418. struct ieee80211_vif *vif;
  419. unsigned int delay;
  420. int ret;
  421. mvm = container_of(work, struct iwl_mvm, tdls_cs.dwork.work);
  422. mutex_lock(&mvm->mutex);
  423. /* called after an active channel switch has finished or timed-out */
  424. iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
  425. /* station might be gone, in that case do nothing */
  426. if (mvm->tdls_cs.peer.sta_id == IWL_MVM_STATION_COUNT)
  427. goto out;
  428. sta = rcu_dereference_protected(
  429. mvm->fw_id_to_mac_id[mvm->tdls_cs.peer.sta_id],
  430. lockdep_is_held(&mvm->mutex));
  431. /* the station may not be here, but if it is, it must be a TDLS peer */
  432. if (!sta || IS_ERR(sta) || WARN_ON(!sta->tdls))
  433. goto out;
  434. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  435. vif = mvmsta->vif;
  436. ret = iwl_mvm_tdls_config_channel_switch(mvm, vif,
  437. TDLS_SEND_CHAN_SW_REQ,
  438. sta->addr,
  439. mvm->tdls_cs.peer.initiator,
  440. mvm->tdls_cs.peer.op_class,
  441. &mvm->tdls_cs.peer.chandef,
  442. 0, 0, 0,
  443. mvm->tdls_cs.peer.skb,
  444. mvm->tdls_cs.peer.ch_sw_tm_ie);
  445. if (ret)
  446. IWL_ERR(mvm, "Not sending TDLS channel switch: %d\n", ret);
  447. /* retry after a DTIM if we failed sending now */
  448. delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
  449. queue_delayed_work(system_wq, &mvm->tdls_cs.dwork,
  450. msecs_to_jiffies(delay));
  451. out:
  452. mutex_unlock(&mvm->mutex);
  453. }
  454. int
  455. iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
  456. struct ieee80211_vif *vif,
  457. struct ieee80211_sta *sta, u8 oper_class,
  458. struct cfg80211_chan_def *chandef,
  459. struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie)
  460. {
  461. struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
  462. struct iwl_mvm_sta *mvmsta;
  463. unsigned int delay;
  464. int ret;
  465. mutex_lock(&mvm->mutex);
  466. IWL_DEBUG_TDLS(mvm, "TDLS channel switch with %pM ch %d width %d\n",
  467. sta->addr, chandef->chan->center_freq, chandef->width);
  468. /* we only support a single peer for channel switching */
  469. if (mvm->tdls_cs.peer.sta_id != IWL_MVM_STATION_COUNT) {
  470. IWL_DEBUG_TDLS(mvm,
  471. "Existing peer. Can't start switch with %pM\n",
  472. sta->addr);
  473. ret = -EBUSY;
  474. goto out;
  475. }
  476. ret = iwl_mvm_tdls_config_channel_switch(mvm, vif,
  477. TDLS_SEND_CHAN_SW_REQ,
  478. sta->addr, sta->tdls_initiator,
  479. oper_class, chandef, 0, 0, 0,
  480. tmpl_skb, ch_sw_tm_ie);
  481. if (ret)
  482. goto out;
  483. /*
  484. * Mark the peer as "in tdls switch" for this vif. We only allow a
  485. * single such peer per vif.
  486. */
  487. mvm->tdls_cs.peer.skb = skb_copy(tmpl_skb, GFP_KERNEL);
  488. if (!mvm->tdls_cs.peer.skb) {
  489. ret = -ENOMEM;
  490. goto out;
  491. }
  492. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  493. mvm->tdls_cs.peer.sta_id = mvmsta->sta_id;
  494. mvm->tdls_cs.peer.chandef = *chandef;
  495. mvm->tdls_cs.peer.initiator = sta->tdls_initiator;
  496. mvm->tdls_cs.peer.op_class = oper_class;
  497. mvm->tdls_cs.peer.ch_sw_tm_ie = ch_sw_tm_ie;
  498. /*
  499. * Wait for 2 DTIM periods before attempting the next switch. The next
  500. * switch will be made sooner if the current one completes before that.
  501. */
  502. delay = 2 * TU_TO_MS(vif->bss_conf.dtim_period *
  503. vif->bss_conf.beacon_int);
  504. mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
  505. msecs_to_jiffies(delay));
  506. out:
  507. mutex_unlock(&mvm->mutex);
  508. return ret;
  509. }
  510. void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
  511. struct ieee80211_vif *vif,
  512. struct ieee80211_sta *sta)
  513. {
  514. struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
  515. struct ieee80211_sta *cur_sta;
  516. bool wait_for_phy = false;
  517. mutex_lock(&mvm->mutex);
  518. IWL_DEBUG_TDLS(mvm, "TDLS cancel channel switch with %pM\n", sta->addr);
  519. /* we only support a single peer for channel switching */
  520. if (mvm->tdls_cs.peer.sta_id == IWL_MVM_STATION_COUNT) {
  521. IWL_DEBUG_TDLS(mvm, "No ch switch peer - %pM\n", sta->addr);
  522. goto out;
  523. }
  524. cur_sta = rcu_dereference_protected(
  525. mvm->fw_id_to_mac_id[mvm->tdls_cs.peer.sta_id],
  526. lockdep_is_held(&mvm->mutex));
  527. /* make sure it's the same peer */
  528. if (cur_sta != sta)
  529. goto out;
  530. /*
  531. * If we're currently in a switch because of the now canceled peer,
  532. * wait a DTIM here to make sure the phy is back on the base channel.
  533. * We can't otherwise force it.
  534. */
  535. if (mvm->tdls_cs.cur_sta_id == mvm->tdls_cs.peer.sta_id &&
  536. mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE)
  537. wait_for_phy = true;
  538. mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
  539. dev_kfree_skb(mvm->tdls_cs.peer.skb);
  540. mvm->tdls_cs.peer.skb = NULL;
  541. out:
  542. mutex_unlock(&mvm->mutex);
  543. /* make sure the phy is on the base channel */
  544. if (wait_for_phy)
  545. msleep(TU_TO_MS(vif->bss_conf.dtim_period *
  546. vif->bss_conf.beacon_int));
  547. /* flush the channel switch state */
  548. flush_delayed_work(&mvm->tdls_cs.dwork);
  549. IWL_DEBUG_TDLS(mvm, "TDLS ending channel switch with %pM\n", sta->addr);
  550. }
  551. void
  552. iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
  553. struct ieee80211_vif *vif,
  554. struct ieee80211_tdls_ch_sw_params *params)
  555. {
  556. struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
  557. enum iwl_tdls_channel_switch_type type;
  558. unsigned int delay;
  559. mutex_lock(&mvm->mutex);
  560. IWL_DEBUG_TDLS(mvm,
  561. "Received TDLS ch switch action %d from %pM status %d\n",
  562. params->action_code, params->sta->addr, params->status);
  563. /*
  564. * we got a non-zero status from a peer we were switching to - move to
  565. * the idle state and retry again later
  566. */
  567. if (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE &&
  568. params->status != 0 &&
  569. mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
  570. mvm->tdls_cs.cur_sta_id != IWL_MVM_STATION_COUNT) {
  571. struct ieee80211_sta *cur_sta;
  572. /* make sure it's the same peer */
  573. cur_sta = rcu_dereference_protected(
  574. mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
  575. lockdep_is_held(&mvm->mutex));
  576. if (cur_sta == params->sta) {
  577. iwl_mvm_tdls_update_cs_state(mvm,
  578. IWL_MVM_TDLS_SW_IDLE);
  579. goto retry;
  580. }
  581. }
  582. type = (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST) ?
  583. TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH : TDLS_MOVE_CH;
  584. iwl_mvm_tdls_config_channel_switch(mvm, vif, type, params->sta->addr,
  585. params->sta->tdls_initiator, 0,
  586. params->chandef, params->timestamp,
  587. params->switch_time,
  588. params->switch_timeout,
  589. params->tmpl_skb,
  590. params->ch_sw_tm_ie);
  591. retry:
  592. /* register a timeout in case we don't succeed in switching */
  593. delay = vif->bss_conf.dtim_period * vif->bss_conf.beacon_int *
  594. 1024 / 1000;
  595. mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
  596. msecs_to_jiffies(delay));
  597. mutex_unlock(&mvm->mutex);
  598. }