1 /* Marvell Wireless LAN device driver: TDLS handling
3 * Copyright (C) 2014, Marvell International Ltd.
5 * This software file (the "File") is distributed by Marvell International
6 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
7 * (the "License"). You may use, redistribute and/or modify this File in
8 * accordance with the terms and conditions of the License, a copy of which
9 * is available on the worldwide web at
10 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
12 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
15 * this warranty disclaimer.
21 #include "11n_rxreorder.h"
23 #define TDLS_REQ_FIX_LEN 6
24 #define TDLS_RESP_FIX_LEN 8
25 #define TDLS_CONFIRM_FIX_LEN 6
28 mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
30 struct mwifiex_ra_list_tbl *ra_list;
31 struct list_head *tid_list;
32 struct sk_buff *skb, *tmp;
33 struct mwifiex_txinfo *tx_info;
38 dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
39 spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
41 skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
42 if (!ether_addr_equal(mac, skb->data))
45 __skb_unlink(skb, &priv->tdls_txq);
46 tx_info = MWIFIEX_SKB_TXCB(skb);
48 tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
50 if (status == TDLS_SETUP_COMPLETE) {
51 ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
52 tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
54 tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
55 if (!list_empty(tid_list))
56 ra_list = list_first_entry(tid_list,
57 struct mwifiex_ra_list_tbl, list);
60 tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
64 mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
68 skb_queue_tail(&ra_list->skb_head, skb);
70 ra_list->ba_pkt_count++;
71 ra_list->total_pkt_count++;
73 if (atomic_read(&priv->wmm.highest_queued_prio) <
74 tos_to_tid_inv[tid_down])
75 atomic_set(&priv->wmm.highest_queued_prio,
76 tos_to_tid_inv[tid_down]);
78 atomic_inc(&priv->wmm.tx_pkts_queued);
81 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
85 static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac)
87 struct mwifiex_ra_list_tbl *ra_list;
88 struct list_head *ra_list_head;
89 struct sk_buff *skb, *tmp;
93 dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
94 spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
96 for (i = 0; i < MAX_NUM_TID; i++) {
97 if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
98 ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
99 list_for_each_entry(ra_list, ra_list_head, list) {
100 skb_queue_walk_safe(&ra_list->skb_head, skb,
102 if (!ether_addr_equal(mac, skb->data))
104 __skb_unlink(skb, &ra_list->skb_head);
105 atomic_dec(&priv->wmm.tx_pkts_queued);
106 ra_list->total_pkt_count--;
107 skb_queue_tail(&priv->tdls_txq, skb);
113 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
117 /* This function appends rate TLV to scan config command. */
119 mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
122 u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
123 u16 rates_size, supp_rates_size, ext_rates_size;
125 memset(rates, 0, sizeof(rates));
126 rates_size = mwifiex_get_supported_rates(priv, rates);
128 supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
130 if (skb_tailroom(skb) < rates_size + 4) {
131 dev_err(priv->adapter->dev,
132 "Insuffient space while adding rates\n");
136 pos = skb_put(skb, supp_rates_size + 2);
137 *pos++ = WLAN_EID_SUPP_RATES;
138 *pos++ = supp_rates_size;
139 memcpy(pos, rates, supp_rates_size);
141 if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
142 ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
143 pos = skb_put(skb, ext_rates_size + 2);
144 *pos++ = WLAN_EID_EXT_SUPP_RATES;
145 *pos++ = ext_rates_size;
146 memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
153 static void mwifiex_tdls_add_ext_capab(struct sk_buff *skb)
155 struct ieee_types_extcap *extcap;
157 extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
158 extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
159 extcap->ieee_hdr.len = 8;
160 memset(extcap->ext_capab, 0, 8);
161 extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
164 static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
166 u8 *pos = (void *)skb_put(skb, 3);
168 *pos++ = WLAN_EID_QOS_CAPA;
170 *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
173 static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
174 u8 *peer, u8 action_code, u8 dialog_token,
175 u16 status_code, struct sk_buff *skb)
177 struct ieee80211_tdls_data *tf;
180 struct ieee80211_ht_cap *ht_cap;
183 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
185 tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
186 memcpy(tf->da, peer, ETH_ALEN);
187 memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
188 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
189 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
191 switch (action_code) {
192 case WLAN_TDLS_SETUP_REQUEST:
193 tf->category = WLAN_CATEGORY_TDLS;
194 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
195 skb_put(skb, sizeof(tf->u.setup_req));
196 tf->u.setup_req.dialog_token = dialog_token;
197 tf->u.setup_req.capability = cpu_to_le16(capab);
198 ret = mwifiex_tdls_append_rates_ie(priv, skb);
200 dev_kfree_skb_any(skb);
204 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
205 *pos++ = WLAN_EID_HT_CAPABILITY;
206 *pos++ = sizeof(struct ieee80211_ht_cap);
207 ht_cap = (void *)pos;
208 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
209 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
211 dev_kfree_skb_any(skb);
215 mwifiex_tdls_add_ext_capab(skb);
216 mwifiex_tdls_add_qos_capab(skb);
219 case WLAN_TDLS_SETUP_RESPONSE:
220 tf->category = WLAN_CATEGORY_TDLS;
221 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
222 skb_put(skb, sizeof(tf->u.setup_resp));
223 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
224 tf->u.setup_resp.dialog_token = dialog_token;
225 tf->u.setup_resp.capability = cpu_to_le16(capab);
226 ret = mwifiex_tdls_append_rates_ie(priv, skb);
228 dev_kfree_skb_any(skb);
232 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
233 *pos++ = WLAN_EID_HT_CAPABILITY;
234 *pos++ = sizeof(struct ieee80211_ht_cap);
235 ht_cap = (void *)pos;
236 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
237 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
239 dev_kfree_skb_any(skb);
243 mwifiex_tdls_add_ext_capab(skb);
244 mwifiex_tdls_add_qos_capab(skb);
247 case WLAN_TDLS_SETUP_CONFIRM:
248 tf->category = WLAN_CATEGORY_TDLS;
249 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
250 skb_put(skb, sizeof(tf->u.setup_cfm));
251 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
252 tf->u.setup_cfm.dialog_token = dialog_token;
255 case WLAN_TDLS_TEARDOWN:
256 tf->category = WLAN_CATEGORY_TDLS;
257 tf->action_code = WLAN_TDLS_TEARDOWN;
258 skb_put(skb, sizeof(tf->u.teardown));
259 tf->u.teardown.reason_code = cpu_to_le16(status_code);
262 case WLAN_TDLS_DISCOVERY_REQUEST:
263 tf->category = WLAN_CATEGORY_TDLS;
264 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
265 skb_put(skb, sizeof(tf->u.discover_req));
266 tf->u.discover_req.dialog_token = dialog_token;
269 dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
277 mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
279 struct ieee80211_tdls_lnkie *lnkid;
281 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
282 lnkid->ie_type = WLAN_EID_LINK_ID;
283 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
284 sizeof(struct ieee_types_header);
286 memcpy(lnkid->bssid, bssid, ETH_ALEN);
287 memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
288 memcpy(lnkid->resp_sta, peer, ETH_ALEN);
291 int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
292 u8 *peer, u8 action_code, u8 dialog_token,
293 u16 status_code, const u8 *extra_ies,
294 size_t extra_ies_len)
297 struct mwifiex_txinfo *tx_info;
302 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
303 max(sizeof(struct ieee80211_mgmt),
304 sizeof(struct ieee80211_tdls_data)) +
305 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
306 MWIFIEX_SUPPORTED_RATES +
308 sizeof(struct ieee_types_extcap) +
309 sizeof(struct ieee80211_ht_cap) +
310 sizeof(struct ieee_types_bss_co_2040) +
311 sizeof(struct ieee80211_ht_operation) +
312 sizeof(struct ieee80211_tdls_lnkie) +
315 skb = dev_alloc_skb(skb_len);
317 dev_err(priv->adapter->dev,
318 "allocate skb failed for management frame\n");
321 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
323 switch (action_code) {
324 case WLAN_TDLS_SETUP_REQUEST:
325 case WLAN_TDLS_SETUP_CONFIRM:
326 case WLAN_TDLS_TEARDOWN:
327 case WLAN_TDLS_DISCOVERY_REQUEST:
328 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
329 dialog_token, status_code,
332 dev_kfree_skb_any(skb);
336 memcpy(skb_put(skb, extra_ies_len), extra_ies,
338 mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
341 case WLAN_TDLS_SETUP_RESPONSE:
342 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
343 dialog_token, status_code,
346 dev_kfree_skb_any(skb);
350 memcpy(skb_put(skb, extra_ies_len), extra_ies,
352 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
357 switch (action_code) {
358 case WLAN_TDLS_SETUP_REQUEST:
359 case WLAN_TDLS_SETUP_RESPONSE:
360 skb->priority = MWIFIEX_PRIO_BK;
363 skb->priority = MWIFIEX_PRIO_VI;
367 tx_info = MWIFIEX_SKB_TXCB(skb);
368 tx_info->bss_num = priv->bss_num;
369 tx_info->bss_type = priv->bss_type;
371 do_gettimeofday(&tv);
372 skb->tstamp = timeval_to_ktime(tv);
373 mwifiex_queue_tx_pkt(priv, skb);
379 mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
380 u8 action_code, u8 dialog_token,
381 u16 status_code, struct sk_buff *skb)
383 struct ieee80211_mgmt *mgmt;
384 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
387 struct ieee80211_ht_cap *ht_cap;
390 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
392 mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
395 memcpy(mgmt->da, peer, ETH_ALEN);
396 memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
397 memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
398 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
399 IEEE80211_STYPE_ACTION);
402 pos = skb_put(skb, ETH_ALEN);
404 switch (action_code) {
405 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
406 skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
407 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
408 mgmt->u.action.u.tdls_discover_resp.action_code =
409 WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
410 mgmt->u.action.u.tdls_discover_resp.dialog_token =
412 mgmt->u.action.u.tdls_discover_resp.capability =
414 /* move back for addr4 */
415 memmove(pos + ETH_ALEN, &mgmt->u.action.category,
416 sizeof(mgmt->u.action.u.tdls_discover_resp));
418 memcpy(pos, bc_addr, ETH_ALEN);
420 ret = mwifiex_tdls_append_rates_ie(priv, skb);
422 dev_kfree_skb_any(skb);
426 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
427 *pos++ = WLAN_EID_HT_CAPABILITY;
428 *pos++ = sizeof(struct ieee80211_ht_cap);
429 ht_cap = (void *)pos;
430 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
431 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
433 dev_kfree_skb_any(skb);
437 mwifiex_tdls_add_ext_capab(skb);
438 mwifiex_tdls_add_qos_capab(skb);
441 dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
448 int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
449 u8 *peer, u8 action_code, u8 dialog_token,
450 u16 status_code, const u8 *extra_ies,
451 size_t extra_ies_len)
454 struct mwifiex_txinfo *tx_info;
457 u32 pkt_type, tx_control;
458 u16 pkt_len, skb_len;
460 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
461 max(sizeof(struct ieee80211_mgmt),
462 sizeof(struct ieee80211_tdls_data)) +
463 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
464 MWIFIEX_SUPPORTED_RATES +
465 sizeof(struct ieee_types_extcap) +
466 sizeof(struct ieee80211_ht_cap) +
467 sizeof(struct ieee_types_bss_co_2040) +
468 sizeof(struct ieee80211_ht_operation) +
469 sizeof(struct ieee80211_tdls_lnkie) +
472 ETH_ALEN; /* Address4 */
474 skb = dev_alloc_skb(skb_len);
476 dev_err(priv->adapter->dev,
477 "allocate skb failed for management frame\n");
481 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
483 pkt_type = PKT_TYPE_MGMT;
485 pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
486 memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
487 memcpy(pos, &pkt_type, sizeof(pkt_type));
488 memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
490 if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
491 dialog_token, status_code,
493 dev_kfree_skb_any(skb);
498 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
500 /* the TDLS link IE is always added last we are the responder */
502 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
505 skb->priority = MWIFIEX_PRIO_VI;
507 tx_info = MWIFIEX_SKB_TXCB(skb);
508 tx_info->bss_num = priv->bss_num;
509 tx_info->bss_type = priv->bss_type;
510 tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
512 pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
513 memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
515 do_gettimeofday(&tv);
516 skb->tstamp = timeval_to_ktime(tv);
517 mwifiex_queue_tx_pkt(priv, skb);
522 /* This function process tdls action frame from peer.
523 * Peer capabilities are stored into station node structure.
525 void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
528 struct mwifiex_sta_node *sta_ptr;
529 u8 *peer, *pos, *end;
533 if (len < (sizeof(struct ethhdr) + 3))
535 if (*(u8 *)(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
537 if (*(u8 *)(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
540 peer = buf + ETH_ALEN;
541 action = *(u8 *)(buf + sizeof(struct ethhdr) + 2);
543 /* just handle TDLS setup request/response/confirm */
544 if (action > WLAN_TDLS_SETUP_CONFIRM)
547 dev_dbg(priv->adapter->dev,
548 "rx:tdls action: peer=%pM, action=%d\n", peer, action);
550 sta_ptr = mwifiex_add_sta_entry(priv, peer);
555 case WLAN_TDLS_SETUP_REQUEST:
556 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
559 pos = buf + sizeof(struct ethhdr) + 4;
560 /* payload 1+ category 1 + action 1 + dialog 1 */
561 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
562 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
566 case WLAN_TDLS_SETUP_RESPONSE:
567 if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
569 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
570 pos = buf + sizeof(struct ethhdr) + 6;
571 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
572 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
576 case WLAN_TDLS_SETUP_CONFIRM:
577 if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
579 pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
580 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
583 dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
587 for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
588 if (pos + 2 + pos[1] > end)
592 case WLAN_EID_SUPP_RATES:
593 sta_ptr->tdls_cap.rates_len = pos[1];
594 for (i = 0; i < pos[1]; i++)
595 sta_ptr->tdls_cap.rates[i] = pos[i + 2];
598 case WLAN_EID_EXT_SUPP_RATES:
599 basic = sta_ptr->tdls_cap.rates_len;
600 for (i = 0; i < pos[1]; i++)
601 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
602 sta_ptr->tdls_cap.rates_len += pos[1];
604 case WLAN_EID_HT_CAPABILITY:
605 memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
606 sizeof(struct ieee80211_ht_cap));
607 sta_ptr->is_11n_enabled = 1;
609 case WLAN_EID_HT_OPERATION:
610 memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
611 sizeof(struct ieee80211_ht_operation));
613 case WLAN_EID_BSS_COEX_2040:
614 sta_ptr->tdls_cap.coex_2040 = pos[2];
616 case WLAN_EID_EXT_CAPABILITY:
617 memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
618 sizeof(struct ieee_types_header) +
619 min_t(u8, pos[1], 8));
622 memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
623 sizeof(struct ieee_types_header) + pos[1]);
625 case WLAN_EID_QOS_CAPA:
626 sta_ptr->tdls_cap.qos_info = pos[2];
637 mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
639 struct mwifiex_sta_node *sta_ptr;
640 struct mwifiex_ds_tdls_oper tdls_oper;
642 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
643 sta_ptr = mwifiex_get_sta_entry(priv, peer);
645 if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
646 dev_err(priv->adapter->dev,
647 "link absent for peer %pM; cannot config\n", peer);
651 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
652 tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
653 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
654 HostCmd_ACT_GEN_SET, 0, &tdls_oper);
658 mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
660 struct mwifiex_sta_node *sta_ptr;
661 struct mwifiex_ds_tdls_oper tdls_oper;
663 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
664 sta_ptr = mwifiex_get_sta_entry(priv, peer);
666 if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
667 dev_dbg(priv->adapter->dev,
668 "Setup already in progress for peer %pM\n", peer);
672 sta_ptr = mwifiex_add_sta_entry(priv, peer);
676 sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
677 mwifiex_hold_tdls_packets(priv, peer);
678 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
679 tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
680 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
681 HostCmd_ACT_GEN_SET, 0, &tdls_oper);
685 mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
687 struct mwifiex_sta_node *sta_ptr;
688 struct mwifiex_ds_tdls_oper tdls_oper;
691 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
692 sta_ptr = mwifiex_get_sta_entry(priv, peer);
695 if (sta_ptr->is_11n_enabled) {
696 mwifiex_11n_cleanup_reorder_tbl(priv);
697 spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
699 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
700 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
703 mwifiex_del_sta_entry(priv, peer);
706 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
707 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
708 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
709 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TDLS_OPER,
710 HostCmd_ACT_GEN_SET, 0, &tdls_oper);
714 mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
716 struct mwifiex_sta_node *sta_ptr;
717 struct ieee80211_mcs_info mcs;
721 sta_ptr = mwifiex_get_sta_entry(priv, peer);
723 if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
724 dev_dbg(priv->adapter->dev,
725 "tdls: enable link %pM success\n", peer);
727 sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
729 mcs = sta_ptr->tdls_cap.ht_capb.mcs;
730 if (mcs.rx_mask[0] != 0xff)
731 sta_ptr->is_11n_enabled = true;
732 if (sta_ptr->is_11n_enabled) {
733 if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
734 IEEE80211_HT_CAP_MAX_AMSDU)
736 MWIFIEX_TX_DATA_BUF_SIZE_8K;
739 MWIFIEX_TX_DATA_BUF_SIZE_4K;
741 for (i = 0; i < MAX_NUM_TID; i++)
742 sta_ptr->ampdu_sta[i] =
743 priv->aggr_prio_tbl[i].ampdu_user;
745 for (i = 0; i < MAX_NUM_TID; i++)
746 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
749 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
750 mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
752 dev_dbg(priv->adapter->dev,
753 "tdls: enable link %pM failed\n", peer);
755 mwifiex_11n_cleanup_reorder_tbl(priv);
756 spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
758 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
759 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
761 mwifiex_del_sta_entry(priv, peer);
763 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
771 int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
774 case MWIFIEX_TDLS_ENABLE_LINK:
775 return mwifiex_tdls_process_enable_link(priv, peer);
776 case MWIFIEX_TDLS_DISABLE_LINK:
777 return mwifiex_tdls_process_disable_link(priv, peer);
778 case MWIFIEX_TDLS_CREATE_LINK:
779 return mwifiex_tdls_process_create_link(priv, peer);
780 case MWIFIEX_TDLS_CONFIG_LINK:
781 return mwifiex_tdls_process_config_link(priv, peer);
786 int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac)
788 struct mwifiex_sta_node *sta_ptr;
790 sta_ptr = mwifiex_get_sta_entry(priv, mac);
792 return sta_ptr->tdls_status;
794 return TDLS_NOT_SETUP;