aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2014-02-07 19:27:33 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-12 15:36:19 -0500
commit5f2caaf32bc64c200007611505ce2453f4862276 (patch)
tree2df3b3978e51b728787b647e4a13a8cb226f4615
parentb23bce296568011b76c27103032dea5a90291d8a (diff)
mwifiex: parse TDLS action frames during RX
This patch adds support for parsing TDLS action frames during station receive handler. Peer station capabilities are stored into station node. Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/mwifiex/decl.h8
-rw-r--r--drivers/net/wireless/mwifiex/main.h19
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c13
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c119
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c5
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h3
6 files changed, 160 insertions, 7 deletions
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index c709f1c25b97..efcd1b8b9a26 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -93,6 +93,14 @@ enum mwifiex_bss_role {
93 MWIFIEX_BSS_ROLE_ANY = 0xff, 93 MWIFIEX_BSS_ROLE_ANY = 0xff,
94}; 94};
95 95
96enum mwifiex_tdls_status {
97 TDLS_NOT_SETUP = 0,
98 TDLS_SETUP_INPROGRESS,
99 TDLS_SETUP_COMPLETE,
100 TDLS_SETUP_FAILURE,
101 TDLS_LINK_TEARDOWN,
102};
103
96#define BSS_ROLE_BIT_MASK BIT(0) 104#define BSS_ROLE_BIT_MASK BIT(0)
97 105
98#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) 106#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK)
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 54197847d494..3b0be45f833c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -594,8 +594,20 @@ struct mwifiex_bss_priv {
594 u64 fw_tsf; 594 u64 fw_tsf;
595}; 595};
596 596
597/* This is AP specific structure which stores information 597struct mwifiex_tdls_capab {
598 * about associated STA 598 __le16 capab;
599 u8 rates[32];
600 u8 rates_len;
601 u8 qos_info;
602 u8 coex_2040;
603 struct ieee80211_ht_cap ht_capb;
604 struct ieee80211_ht_operation ht_oper;
605 struct ieee_types_extcap extcap;
606 struct ieee_types_generic rsn_ie;
607};
608
609/* This is AP/TDLS specific structure which stores information
610 * about associated/peer STA
599 */ 611 */
600struct mwifiex_sta_node { 612struct mwifiex_sta_node {
601 struct list_head list; 613 struct list_head list;
@@ -605,6 +617,7 @@ struct mwifiex_sta_node {
605 u8 ampdu_sta[MAX_NUM_TID]; 617 u8 ampdu_sta[MAX_NUM_TID];
606 u16 rx_seq[MAX_NUM_TID]; 618 u16 rx_seq[MAX_NUM_TID];
607 u16 max_amsdu; 619 u16 max_amsdu;
620 struct mwifiex_tdls_capab tdls_cap;
608}; 621};
609 622
610struct mwifiex_if_ops { 623struct mwifiex_if_ops {
@@ -1194,6 +1207,8 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
1194 u8 *peer, u8 action_code, u8 dialog_token, 1207 u8 *peer, u8 action_code, u8 dialog_token,
1195 u16 status_code, const u8 *extra_ies, 1208 u16 status_code, const u8 *extra_ies,
1196 size_t extra_ies_len); 1209 size_t extra_ies_len);
1210void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
1211 u8 *buf, int len);
1197 1212
1198#ifdef CONFIG_DEBUG_FS 1213#ifdef CONFIG_DEBUG_FS
1199void mwifiex_debugfs_init(void); 1214void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 4651d676df38..b6aa958bd6e4 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -88,11 +88,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
88 struct rxpd *local_rx_pd; 88 struct rxpd *local_rx_pd;
89 int hdr_chop; 89 int hdr_chop;
90 struct ethhdr *eth; 90 struct ethhdr *eth;
91 u16 rx_pkt_off, rx_pkt_len;
92 u8 *offset;
91 93
92 local_rx_pd = (struct rxpd *) (skb->data); 94 local_rx_pd = (struct rxpd *) (skb->data);
93 95
94 rx_pkt_hdr = (void *)local_rx_pd + 96 rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset);
95 le16_to_cpu(local_rx_pd->rx_pkt_offset); 97 rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
98 rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
96 99
97 if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, 100 if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
98 sizeof(bridge_tunnel_header))) || 101 sizeof(bridge_tunnel_header))) ||
@@ -142,6 +145,12 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
142 return 0; 145 return 0;
143 } 146 }
144 147
148 if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
149 ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
150 offset = (u8 *)local_rx_pd + rx_pkt_off;
151 mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len);
152 }
153
145 priv->rxpd_rate = local_rx_pd->rx_rate; 154 priv->rxpd_rate = local_rx_pd->rx_rate;
146 155
147 priv->rxpd_htinfo = local_rx_pd->ht_info; 156 priv->rxpd_htinfo = local_rx_pd->ht_info;
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 73cd444a6d43..ba54037a324c 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -16,6 +16,11 @@
16 */ 16 */
17 17
18#include "main.h" 18#include "main.h"
19#include "wmm.h"
20
21#define TDLS_REQ_FIX_LEN 6
22#define TDLS_RESP_FIX_LEN 8
23#define TDLS_CONFIRM_FIX_LEN 6
19 24
20/* This function appends rate TLV to scan config command. */ 25/* This function appends rate TLV to scan config command. */
21static int 26static int
@@ -421,3 +426,117 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
421 426
422 return 0; 427 return 0;
423} 428}
429
430/* This function process tdls action frame from peer.
431 * Peer capabilities are stored into station node structure.
432 */
433void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
434 u8 *buf, int len)
435{
436 struct mwifiex_sta_node *sta_ptr;
437 u8 *peer, *pos, *end;
438 u8 i, action, basic;
439 int ie_len = 0;
440
441 if (len < (sizeof(struct ethhdr) + 3))
442 return;
443 if (*(u8 *)(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
444 return;
445 if (*(u8 *)(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
446 return;
447
448 peer = buf + ETH_ALEN;
449 action = *(u8 *)(buf + sizeof(struct ethhdr) + 2);
450
451 /* just handle TDLS setup request/response/confirm */
452 if (action > WLAN_TDLS_SETUP_CONFIRM)
453 return;
454
455 dev_dbg(priv->adapter->dev,
456 "rx:tdls action: peer=%pM, action=%d\n", peer, action);
457
458 sta_ptr = mwifiex_add_sta_entry(priv, peer);
459 if (!sta_ptr)
460 return;
461
462 switch (action) {
463 case WLAN_TDLS_SETUP_REQUEST:
464 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
465 return;
466
467 pos = buf + sizeof(struct ethhdr) + 4;
468 /* payload 1+ category 1 + action 1 + dialog 1 */
469 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
470 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
471 pos += 2;
472 break;
473
474 case WLAN_TDLS_SETUP_RESPONSE:
475 if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
476 return;
477 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
478 pos = buf + sizeof(struct ethhdr) + 6;
479 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
480 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
481 pos += 2;
482 break;
483
484 case WLAN_TDLS_SETUP_CONFIRM:
485 if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
486 return;
487 pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
488 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
489 break;
490 default:
491 dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
492 return;
493 }
494
495 for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
496 if (pos + 2 + pos[1] > end)
497 break;
498
499 switch (*pos) {
500 case WLAN_EID_SUPP_RATES:
501 sta_ptr->tdls_cap.rates_len = pos[1];
502 for (i = 0; i < pos[1]; i++)
503 sta_ptr->tdls_cap.rates[i] = pos[i + 2];
504 break;
505
506 case WLAN_EID_EXT_SUPP_RATES:
507 basic = sta_ptr->tdls_cap.rates_len;
508 for (i = 0; i < pos[1]; i++)
509 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
510 sta_ptr->tdls_cap.rates_len += pos[1];
511 break;
512 case WLAN_EID_HT_CAPABILITY:
513 memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
514 sizeof(struct ieee80211_ht_cap));
515 sta_ptr->is_11n_enabled = 1;
516 break;
517 case WLAN_EID_HT_OPERATION:
518 memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
519 sizeof(struct ieee80211_ht_operation));
520 break;
521 case WLAN_EID_BSS_COEX_2040:
522 sta_ptr->tdls_cap.coex_2040 = pos[2];
523 break;
524 case WLAN_EID_EXT_CAPABILITY:
525 memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
526 sizeof(struct ieee_types_header) +
527 min_t(u8, pos[1], 8));
528 break;
529 case WLAN_EID_RSN:
530 memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
531 sizeof(struct ieee_types_header) + pos[1]);
532 break;
533 case WLAN_EID_QOS_CAPA:
534 sta_ptr->tdls_cap.qos_info = pos[2];
535 break;
536 default:
537 break;
538 }
539 }
540
541 return;
542}
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 2999c3b1e112..557d36318d1d 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -374,8 +374,7 @@ mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos)
374 * AP is disabled (due to call admission control (ACM bit). Mapping 374 * AP is disabled (due to call admission control (ACM bit). Mapping
375 * of TID to AC is taken care of internally. 375 * of TID to AC is taken care of internally.
376 */ 376 */
377static u8 377u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid)
378mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid)
379{ 378{
380 enum mwifiex_wmm_ac_e ac, ac_down; 379 enum mwifiex_wmm_ac_e ac, ac_down;
381 u8 new_tid; 380 u8 new_tid;
@@ -578,7 +577,7 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
578 * If no such node is found, a new node is added first and then 577 * If no such node is found, a new node is added first and then
579 * retrieved. 578 * retrieved.
580 */ 579 */
581static struct mwifiex_ra_list_tbl * 580struct mwifiex_ra_list_tbl *
582mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) 581mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)
583{ 582{
584 struct mwifiex_ra_list_tbl *ra_list; 583 struct mwifiex_ra_list_tbl *ra_list;
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index d4e607395da7..83e42083ebff 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -122,5 +122,8 @@ void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
122void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); 122void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv);
123int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, 123int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
124 const struct host_cmd_ds_command *resp); 124 const struct host_cmd_ds_command *resp);
125struct mwifiex_ra_list_tbl *
126mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr);
127u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
125 128
126#endif /* !_MWIFIEX_WMM_H_ */ 129#endif /* !_MWIFIEX_WMM_H_ */