diff options
author | Avinash Patil <patila@marvell.com> | 2014-02-07 19:27:33 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-12 15:36:19 -0500 |
commit | 5f2caaf32bc64c200007611505ce2453f4862276 (patch) | |
tree | 2df3b3978e51b728787b647e4a13a8cb226f4615 | |
parent | b23bce296568011b76c27103032dea5a90291d8a (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.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_rx.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/tdls.c | 119 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.h | 3 |
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 | ||
96 | enum 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 | 597 | struct 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 | */ |
600 | struct mwifiex_sta_node { | 612 | struct 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 | ||
610 | struct mwifiex_if_ops { | 623 | struct 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); |
1210 | void 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 |
1199 | void mwifiex_debugfs_init(void); | 1214 | void 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. */ |
21 | static int | 26 | static 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 | */ | ||
433 | void 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 | */ |
377 | static u8 | 377 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) |
378 | mwifiex_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 | */ |
581 | static struct mwifiex_ra_list_tbl * | 580 | struct mwifiex_ra_list_tbl * |
582 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) | 581 | mwifiex_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, | |||
122 | void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); | 122 | void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); |
123 | int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, | 123 | int 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); |
125 | struct mwifiex_ra_list_tbl * | ||
126 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr); | ||
127 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); | ||
125 | 128 | ||
126 | #endif /* !_MWIFIEX_WMM_H_ */ | 129 | #endif /* !_MWIFIEX_WMM_H_ */ |