aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ketrenos <jketreno@linux.intel.com>2005-09-21 12:56:33 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-21 23:03:54 -0400
commit9e8571affd1c54b9638b4ff9844e47aae07310f6 (patch)
treef6e568913c2d8aa1bf6bfedb3d90a78f2ade747b
parent2c0aa2a5c2dfa1293ae3a07517d0b7de149358a1 (diff)
[PATCH] ieee80211: Add QoS (WME) support to the ieee80211 subsystem
tree a3ad796273e98036eb0e9fc063225070fa24508a parent 1b9c0aeb377abf8e4a43a86cff42382f74ca0259 author Mohamed Abbas <mabbas@linux.intel.com> 1124447069 -0500 committer James Ketrenos <jketreno@linux.intel.com> 1127313435 -0500 Add QoS (WME) support to the ieee80211 subsystem. NOTE: This requires drivers that use the ieee80211 hard_start_xmit (ipw2100 and ipw2200) to add the priority parameter to their callback. Signed-off-by: James Ketrenos <jketreno@linux.intel.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--include/net/ieee80211.h103
-rw-r--r--net/ieee80211/ieee80211_rx.c334
-rw-r--r--net/ieee80211/ieee80211_tx.c5
3 files changed, 417 insertions, 25 deletions
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index 46466f5a2b45..72bd2b17eeb4 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -92,6 +92,7 @@
92#define IEEE80211_STYPE_CFACK 0x0050 92#define IEEE80211_STYPE_CFACK 0x0050
93#define IEEE80211_STYPE_CFPOLL 0x0060 93#define IEEE80211_STYPE_CFPOLL 0x0060
94#define IEEE80211_STYPE_CFACKPOLL 0x0070 94#define IEEE80211_STYPE_CFACKPOLL 0x0070
95#define IEEE80211_STYPE_QOS_DATA 0x0080
95 96
96#define IEEE80211_SCTL_FRAG 0x000F 97#define IEEE80211_SCTL_FRAG 0x000F
97#define IEEE80211_SCTL_SEQ 0xFFF0 98#define IEEE80211_SCTL_SEQ 0xFFF0
@@ -153,6 +154,7 @@ const char *escape_essid(const char *essid, u8 essid_len);
153 154
154#define IEEE80211_DL_TX (1<<8) 155#define IEEE80211_DL_TX (1<<8)
155#define IEEE80211_DL_RX (1<<9) 156#define IEEE80211_DL_RX (1<<9)
157#define IEEE80211_DL_QOS (1<<31)
156 158
157#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) 159#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
158#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) 160#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
@@ -166,6 +168,7 @@ const char *escape_essid(const char *essid, u8 essid_len);
166#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) 168#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
167#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) 169#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
168#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) 170#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
171#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
169#include <linux/netdevice.h> 172#include <linux/netdevice.h>
170#include <linux/wireless.h> 173#include <linux/wireless.h>
171#include <linux/if_arp.h> /* ARPHRD_ETHER */ 174#include <linux/if_arp.h> /* ARPHRD_ETHER */
@@ -493,6 +496,7 @@ enum ieee80211_mfie {
493 MFIE_TYPE_RSN = 48, 496 MFIE_TYPE_RSN = 48,
494 MFIE_TYPE_RATES_EX = 50, 497 MFIE_TYPE_RATES_EX = 50,
495 MFIE_TYPE_GENERIC = 221, 498 MFIE_TYPE_GENERIC = 221,
499 MFIE_TYPE_QOS_PARAMETER = 222,
496}; 500};
497 501
498/* Minimal header; can be used for passing 802.11 frames with sufficient 502/* Minimal header; can be used for passing 802.11 frames with sufficient
@@ -540,6 +544,29 @@ struct ieee80211_hdr_4addr {
540 u8 payload[0]; 544 u8 payload[0];
541} __attribute__ ((packed)); 545} __attribute__ ((packed));
542 546
547struct ieee80211_hdr_3addrqos {
548 u16 frame_ctl;
549 u16 duration_id;
550 u8 addr1[ETH_ALEN];
551 u8 addr2[ETH_ALEN];
552 u8 addr3[ETH_ALEN];
553 u16 seq_ctl;
554 u8 payload[0];
555 u16 qos_ctl;
556} __attribute__ ((packed));
557
558struct ieee80211_hdr_4addrqos {
559 u16 frame_ctl;
560 u16 duration_id;
561 u8 addr1[ETH_ALEN];
562 u8 addr2[ETH_ALEN];
563 u8 addr3[ETH_ALEN];
564 u16 seq_ctl;
565 u8 addr4[ETH_ALEN];
566 u8 payload[0];
567 u16 qos_ctl;
568} __attribute__ ((packed));
569
543struct ieee80211_info_element { 570struct ieee80211_info_element {
544 u8 id; 571 u8 id;
545 u8 len; 572 u8 len;
@@ -641,9 +668,68 @@ struct ieee80211_txb {
641 668
642#define MAX_WPA_IE_LEN 64 669#define MAX_WPA_IE_LEN 64
643 670
644#define NETWORK_EMPTY_ESSID (1<<0) 671#define NETWORK_EMPTY_ESSID (1<<0)
645#define NETWORK_HAS_OFDM (1<<1) 672#define NETWORK_HAS_OFDM (1<<1)
646#define NETWORK_HAS_CCK (1<<2) 673#define NETWORK_HAS_CCK (1<<2)
674
675/* QoS structure */
676#define NETWORK_HAS_QOS_PARAMETERS (1<<3)
677#define NETWORK_HAS_QOS_INFORMATION (1<<4)
678#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | NETWORK_HAS_QOS_INFORMATION)
679
680#define QOS_QUEUE_NUM 4
681#define QOS_OUI_LEN 3
682#define QOS_OUI_TYPE 2
683#define QOS_ELEMENT_ID 221
684#define QOS_OUI_INFO_SUB_TYPE 0
685#define QOS_OUI_PARAM_SUB_TYPE 1
686#define QOS_VERSION_1 1
687#define QOS_AIFSN_MIN_VALUE 2
688
689struct ieee80211_qos_information_element {
690 u8 elementID;
691 u8 length;
692 u8 qui[QOS_OUI_LEN];
693 u8 qui_type;
694 u8 qui_subtype;
695 u8 version;
696 u8 ac_info;
697} __attribute__ ((packed));
698
699struct ieee80211_qos_ac_parameter {
700 u8 aci_aifsn;
701 u8 ecw_min_max;
702 u16 tx_op_limit;
703} __attribute__ ((packed));
704
705struct ieee80211_qos_parameter_info {
706 struct ieee80211_qos_information_element info_element;
707 u8 reserved;
708 struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
709} __attribute__ ((packed));
710
711struct ieee80211_qos_parameters {
712 u16 cw_min[QOS_QUEUE_NUM];
713 u16 cw_max[QOS_QUEUE_NUM];
714 u8 aifs[QOS_QUEUE_NUM];
715 u8 flag[QOS_QUEUE_NUM];
716 u16 tx_op_limit[QOS_QUEUE_NUM];
717} __attribute__ ((packed));
718
719struct ieee80211_qos_data {
720 struct ieee80211_qos_parameters parameters;
721 int active;
722 int supported;
723 u8 param_count;
724 u8 old_param_count;
725};
726
727struct ieee80211_tim_parameters {
728 u8 tim_count;
729 u8 tim_period;
730} __attribute__ ((packed));
731
732/*******************************************************/
647 733
648struct ieee80211_network { 734struct ieee80211_network {
649 /* These entries are used to identify a unique network */ 735 /* These entries are used to identify a unique network */
@@ -653,6 +739,8 @@ struct ieee80211_network {
653 u8 ssid[IW_ESSID_MAX_SIZE + 1]; 739 u8 ssid[IW_ESSID_MAX_SIZE + 1];
654 u8 ssid_len; 740 u8 ssid_len;
655 741
742 struct ieee80211_qos_data qos_data;
743
656 /* These are network statistics */ 744 /* These are network statistics */
657 struct ieee80211_rx_stats stats; 745 struct ieee80211_rx_stats stats;
658 u16 capability; 746 u16 capability;
@@ -672,6 +760,7 @@ struct ieee80211_network {
672 size_t wpa_ie_len; 760 size_t wpa_ie_len;
673 u8 rsn_ie[MAX_WPA_IE_LEN]; 761 u8 rsn_ie[MAX_WPA_IE_LEN];
674 size_t rsn_ie_len; 762 size_t rsn_ie_len;
763 struct ieee80211_tim_parameters tim;
675 struct list_head list; 764 struct list_head list;
676}; 765};
677 766
@@ -769,10 +858,13 @@ struct ieee80211_device {
769 void (*set_security) (struct net_device * dev, 858 void (*set_security) (struct net_device * dev,
770 struct ieee80211_security * sec); 859 struct ieee80211_security * sec);
771 int (*hard_start_xmit) (struct ieee80211_txb * txb, 860 int (*hard_start_xmit) (struct ieee80211_txb * txb,
772 struct net_device * dev); 861 struct net_device * dev, int pri);
773 int (*reset_port) (struct net_device * dev); 862 int (*reset_port) (struct net_device * dev);
774 int (*is_queue_full) (struct net_device * dev, int pri); 863 int (*is_queue_full) (struct net_device * dev, int pri);
775 864
865 int (*handle_management) (struct net_device * dev,
866 struct ieee80211_network * network, u16 type);
867
776 /* Typical STA methods */ 868 /* Typical STA methods */
777 int (*handle_auth) (struct net_device * dev, 869 int (*handle_auth) (struct net_device * dev,
778 struct ieee80211_auth * auth); 870 struct ieee80211_auth * auth);
@@ -854,11 +946,14 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee,
854extern inline int ieee80211_get_hdrlen(u16 fc) 946extern inline int ieee80211_get_hdrlen(u16 fc)
855{ 947{
856 int hdrlen = IEEE80211_3ADDR_LEN; 948 int hdrlen = IEEE80211_3ADDR_LEN;
949 u16 stype = WLAN_FC_GET_STYPE(fc);
857 950
858 switch (WLAN_FC_GET_TYPE(fc)) { 951 switch (WLAN_FC_GET_TYPE(fc)) {
859 case IEEE80211_FTYPE_DATA: 952 case IEEE80211_FTYPE_DATA:
860 if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) 953 if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
861 hdrlen = IEEE80211_4ADDR_LEN; 954 hdrlen = IEEE80211_4ADDR_LEN;
955 if (stype & IEEE80211_STYPE_QOS_DATA)
956 hdrlen += 2;
862 break; 957 break;
863 case IEEE80211_FTYPE_CTL: 958 case IEEE80211_FTYPE_CTL:
864 switch (WLAN_FC_GET_STYPE(fc)) { 959 switch (WLAN_FC_GET_STYPE(fc)) {
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index d1ae28280d7e..2c4613527dfd 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -534,6 +534,9 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
534 534
535 /* Nullfunc frames may have PS-bit set, so they must be passed to 535 /* Nullfunc frames may have PS-bit set, so they must be passed to
536 * hostap_handle_sta_rx() before being dropped here. */ 536 * hostap_handle_sta_rx() before being dropped here. */
537
538 stype &= ~IEEE80211_STYPE_QOS_DATA;
539
537 if (stype != IEEE80211_STYPE_DATA && 540 if (stype != IEEE80211_STYPE_DATA &&
538 stype != IEEE80211_STYPE_DATA_CFACK && 541 stype != IEEE80211_STYPE_DATA_CFACK &&
539 stype != IEEE80211_STYPE_DATA_CFPOLL && 542 stype != IEEE80211_STYPE_DATA_CFPOLL &&
@@ -758,6 +761,264 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
758 761
759#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 762#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
760 763
764static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
765
766/*
767* Make ther structure we read from the beacon packet has
768* the right values
769*/
770static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
771 *info_element, int sub_type)
772{
773
774 if (info_element->qui_subtype != sub_type)
775 return -1;
776 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
777 return -1;
778 if (info_element->qui_type != QOS_OUI_TYPE)
779 return -1;
780 if (info_element->version != QOS_VERSION_1)
781 return -1;
782
783 return 0;
784}
785
786/*
787 * Parse a QoS parameter element
788 */
789static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
790 *element_param, struct ieee80211_info_element
791 *info_element)
792{
793 int ret = 0;
794 u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
795
796 if ((info_element == NULL) || (element_param == NULL))
797 return -1;
798
799 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
800 memcpy(element_param->info_element.qui, info_element->data,
801 info_element->len);
802 element_param->info_element.elementID = info_element->id;
803 element_param->info_element.length = info_element->len;
804 } else
805 ret = -1;
806 if (ret == 0)
807 ret = ieee80211_verify_qos_info(&element_param->info_element,
808 QOS_OUI_PARAM_SUB_TYPE);
809 return ret;
810}
811
812/*
813 * Parse a QoS information element
814 */
815static int ieee80211_read_qos_info_element(struct
816 ieee80211_qos_information_element
817 *element_info, struct ieee80211_info_element
818 *info_element)
819{
820 int ret = 0;
821 u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
822
823 if (element_info == NULL)
824 return -1;
825 if (info_element == NULL)
826 return -1;
827
828 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
829 memcpy(element_info->qui, info_element->data,
830 info_element->len);
831 element_info->elementID = info_element->id;
832 element_info->length = info_element->len;
833 } else
834 ret = -1;
835
836 if (ret == 0)
837 ret = ieee80211_verify_qos_info(element_info,
838 QOS_OUI_INFO_SUB_TYPE);
839 return ret;
840}
841
842/*
843 * Write QoS parameters from the ac parameters.
844 */
845static int ieee80211_qos_convert_ac_to_parameters(struct
846 ieee80211_qos_parameter_info
847 *param_elm, struct
848 ieee80211_qos_parameters
849 *qos_param)
850{
851 int rc = 0;
852 int i;
853 struct ieee80211_qos_ac_parameter *ac_params;
854 u32 txop;
855 u8 cw_min;
856 u8 cw_max;
857
858 for (i = 0; i < QOS_QUEUE_NUM; i++) {
859 ac_params = &(param_elm->ac_params_record[i]);
860
861 qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
862 qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
863
864 cw_min = ac_params->ecw_min_max & 0x0F;
865 qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);
866
867 cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
868 qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);
869
870 qos_param->flag[i] =
871 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
872
873 txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
874 qos_param->tx_op_limit[i] = (u16) txop;
875 }
876 return rc;
877}
878
879/*
880 * we have a generic data element which it may contain QoS information or
881 * parameters element. check the information element length to decide
882 * which type to read
883 */
884static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
885 *info_element,
886 struct ieee80211_network *network)
887{
888 int rc = 0;
889 struct ieee80211_qos_parameters *qos_param = NULL;
890 struct ieee80211_qos_information_element qos_info_element;
891
892 rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
893
894 if (rc == 0) {
895 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
896 network->flags |= NETWORK_HAS_QOS_INFORMATION;
897 } else {
898 struct ieee80211_qos_parameter_info param_element;
899
900 rc = ieee80211_read_qos_param_element(&param_element,
901 info_element);
902 if (rc == 0) {
903 qos_param = &(network->qos_data.parameters);
904 ieee80211_qos_convert_ac_to_parameters(&param_element,
905 qos_param);
906 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
907 network->qos_data.param_count =
908 param_element.info_element.ac_info & 0x0F;
909 }
910 }
911
912 if (rc == 0) {
913 IEEE80211_DEBUG_QOS("QoS is supported\n");
914 network->qos_data.supported = 1;
915 }
916 return rc;
917}
918
919static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
920 *frame, struct ieee80211_rx_stats *stats)
921{
922 struct ieee80211_network network_resp;
923 struct ieee80211_network *network = &network_resp;
924 struct ieee80211_info_element *info_element;
925 struct net_device *dev = ieee->dev;
926 u16 left;
927
928 network->flags = 0;
929 network->qos_data.active = 0;
930 network->qos_data.supported = 0;
931 network->qos_data.param_count = 0;
932 network->qos_data.old_param_count = 0;
933
934 //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
935 network->atim_window = le16_to_cpu(frame->aid);
936 network->listen_interval = le16_to_cpu(frame->status);
937
938 info_element = frame->info_element;
939 left = stats->len - sizeof(*frame);
940
941 while (left >= sizeof(struct ieee80211_info_element)) {
942 if (sizeof(struct ieee80211_info_element) +
943 info_element->len > left) {
944 IEEE80211_DEBUG_QOS("ASSOC RESP: parse failed: "
945 "info_element->len + 2 > left : "
946 "info_element->len+2=%zd left=%d, id=%d.\n",
947 info_element->len +
948 sizeof(struct
949 ieee80211_info_element),
950 left, info_element->id);
951 return 1;
952 }
953
954 switch (info_element->id) {
955 case MFIE_TYPE_SSID:
956 if (ieee80211_is_empty_essid(info_element->data,
957 info_element->len)) {
958 network->flags |= NETWORK_EMPTY_ESSID;
959 break;
960 }
961
962 network->ssid_len = min(info_element->len,
963 (u8) IW_ESSID_MAX_SIZE);
964 memcpy(network->ssid, info_element->data,
965 network->ssid_len);
966 if (network->ssid_len < IW_ESSID_MAX_SIZE)
967 memset(network->ssid + network->ssid_len, 0,
968 IW_ESSID_MAX_SIZE - network->ssid_len);
969
970 IEEE80211_DEBUG_QOS("MFIE_TYPE_SSID: '%s' len=%d.\n",
971 network->ssid, network->ssid_len);
972 break;
973
974 case MFIE_TYPE_TIM:
975 IEEE80211_DEBUG_QOS("MFIE_TYPE_TIM: ignored\n");
976 break;
977
978 case MFIE_TYPE_IBSS_SET:
979 IEEE80211_DEBUG_QOS("MFIE_TYPE_IBSS_SET: ignored\n");
980 break;
981
982 case MFIE_TYPE_CHALLENGE:
983 IEEE80211_DEBUG_QOS("MFIE_TYPE_CHALLENGE: ignored\n");
984 break;
985
986 case MFIE_TYPE_GENERIC:
987 IEEE80211_DEBUG_QOS("MFIE_TYPE_GENERIC: %d bytes\n",
988 info_element->len);
989 ieee80211_parse_qos_info_param_IE(info_element,
990 network);
991 break;
992
993 case MFIE_TYPE_RSN:
994 IEEE80211_DEBUG_QOS("MFIE_TYPE_RSN: %d bytes\n",
995 info_element->len);
996 break;
997
998 case MFIE_TYPE_QOS_PARAMETER:
999 printk("QoS Error need to parse QOS_PARAMETER IE\n");
1000 break;
1001
1002 default:
1003 IEEE80211_DEBUG_QOS("unsupported IE %d\n",
1004 info_element->id);
1005 break;
1006 }
1007
1008 left -= sizeof(struct ieee80211_info_element) +
1009 info_element->len;
1010 info_element = (struct ieee80211_info_element *)
1011 &info_element->data[info_element->len];
1012 }
1013
1014 if (ieee->handle_assoc_response != NULL)
1015 ieee->handle_assoc_response(dev, frame, network);
1016
1017 return 0;
1018}
1019
1020/***************************************************/
1021
761static inline int ieee80211_is_ofdm_rate(u8 rate) 1022static inline int ieee80211_is_ofdm_rate(u8 rate)
762{ 1023{
763 switch (rate & ~IEEE80211_BASIC_RATE_MASK) { 1024 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
@@ -786,6 +1047,9 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
786 struct ieee80211_info_element *info_element; 1047 struct ieee80211_info_element *info_element;
787 u16 left; 1048 u16 left;
788 u8 i; 1049 u8 i;
1050 network->qos_data.active = 0;
1051 network->qos_data.supported = 0;
1052 network->qos_data.param_count = 0;
789 1053
790 /* Pull out fixed field data */ 1054 /* Pull out fixed field data */
791 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); 1055 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
@@ -813,13 +1077,11 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
813 1077
814 info_element = beacon->info_element; 1078 info_element = beacon->info_element;
815 left = stats->len - sizeof(*beacon); 1079 left = stats->len - sizeof(*beacon);
816 while (left >= sizeof(struct ieee80211_info_element)) { 1080 while (left >= sizeof(*info_element)) {
817 if (sizeof(struct ieee80211_info_element) + info_element->len > 1081 if (sizeof(*info_element) + info_element->len > left) {
818 left) {
819 IEEE80211_DEBUG_SCAN 1082 IEEE80211_DEBUG_SCAN
820 ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n", 1083 ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
821 info_element->len + 1084 info_element->len + sizeof(*info_element), left);
822 sizeof(struct ieee80211_info_element), left);
823 return 1; 1085 return 1;
824 } 1086 }
825 1087
@@ -847,15 +1109,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
847#ifdef CONFIG_IEEE80211_DEBUG 1109#ifdef CONFIG_IEEE80211_DEBUG
848 p = rates_str; 1110 p = rates_str;
849#endif 1111#endif
850 network->rates_len = 1112 network->rates_len = min(info_element->len,
851 min(info_element->len, MAX_RATES_LENGTH); 1113 MAX_RATES_LENGTH);
852 for (i = 0; i < network->rates_len; i++) { 1114 for (i = 0; i < network->rates_len; i++) {
853 network->rates[i] = info_element->data[i]; 1115 network->rates[i] = info_element->data[i];
854#ifdef CONFIG_IEEE80211_DEBUG 1116#ifdef CONFIG_IEEE80211_DEBUG
855 p += snprintf(p, 1117 p += snprintf(p, sizeof(rates_str) -
856 sizeof(rates_str) - (p - 1118 (p - rates_str), "%02X ",
857 rates_str), 1119 network->rates[i]);
858 "%02X ", network->rates[i]);
859#endif 1120#endif
860 if (ieee80211_is_ofdm_rate 1121 if (ieee80211_is_ofdm_rate
861 (info_element->data[i])) { 1122 (info_element->data[i])) {
@@ -875,15 +1136,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
875#ifdef CONFIG_IEEE80211_DEBUG 1136#ifdef CONFIG_IEEE80211_DEBUG
876 p = rates_str; 1137 p = rates_str;
877#endif 1138#endif
878 network->rates_ex_len = 1139 network->rates_ex_len = min(info_element->len,
879 min(info_element->len, MAX_RATES_EX_LENGTH); 1140 MAX_RATES_EX_LENGTH);
880 for (i = 0; i < network->rates_ex_len; i++) { 1141 for (i = 0; i < network->rates_ex_len; i++) {
881 network->rates_ex[i] = info_element->data[i]; 1142 network->rates_ex[i] = info_element->data[i];
882#ifdef CONFIG_IEEE80211_DEBUG 1143#ifdef CONFIG_IEEE80211_DEBUG
883 p += snprintf(p, 1144 p += snprintf(p, sizeof(rates_str) -
884 sizeof(rates_str) - (p - 1145 (p - rates_str), "%02X ",
885 rates_str), 1146 network->rates[i]);
886 "%02X ", network->rates[i]);
887#endif 1147#endif
888 if (ieee80211_is_ofdm_rate 1148 if (ieee80211_is_ofdm_rate
889 (info_element->data[i])) { 1149 (info_element->data[i])) {
@@ -929,6 +1189,10 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
929 case MFIE_TYPE_GENERIC: 1189 case MFIE_TYPE_GENERIC:
930 IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", 1190 IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
931 info_element->len); 1191 info_element->len);
1192 if (!ieee80211_parse_qos_info_param_IE(info_element,
1193 network))
1194 break;
1195
932 if (info_element->len >= 4 && 1196 if (info_element->len >= 4 &&
933 info_element->data[0] == 0x00 && 1197 info_element->data[0] == 0x00 &&
934 info_element->data[1] == 0x50 && 1198 info_element->data[1] == 0x50 &&
@@ -950,14 +1214,18 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct i
950 network->rsn_ie_len); 1214 network->rsn_ie_len);
951 break; 1215 break;
952 1216
1217 case MFIE_TYPE_QOS_PARAMETER:
1218 printk(KERN_ERR
1219 "QoS Error need to parse QOS_PARAMETER IE\n");
1220 break;
1221
953 default: 1222 default:
954 IEEE80211_DEBUG_SCAN("unsupported IE %d\n", 1223 IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
955 info_element->id); 1224 info_element->id);
956 break; 1225 break;
957 } 1226 }
958 1227
959 left -= sizeof(struct ieee80211_info_element) + 1228 left -= sizeof(*info_element) + info_element->len;
960 info_element->len;
961 info_element = (struct ieee80211_info_element *) 1229 info_element = (struct ieee80211_info_element *)
962 &info_element->data[info_element->len]; 1230 &info_element->data[info_element->len];
963 } 1231 }
@@ -1004,6 +1272,9 @@ static inline int is_same_network(struct ieee80211_network *src,
1004static inline void update_network(struct ieee80211_network *dst, 1272static inline void update_network(struct ieee80211_network *dst,
1005 struct ieee80211_network *src) 1273 struct ieee80211_network *src)
1006{ 1274{
1275 int qos_active;
1276 u8 old_param;
1277
1007 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 1278 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1008 dst->capability = src->capability; 1279 dst->capability = src->capability;
1009 memcpy(dst->rates, src->rates, src->rates_len); 1280 memcpy(dst->rates, src->rates, src->rates_len);
@@ -1026,6 +1297,28 @@ static inline void update_network(struct ieee80211_network *dst,
1026 dst->rsn_ie_len = src->rsn_ie_len; 1297 dst->rsn_ie_len = src->rsn_ie_len;
1027 1298
1028 dst->last_scanned = jiffies; 1299 dst->last_scanned = jiffies;
1300 qos_active = src->qos_data.active;
1301 old_param = dst->qos_data.old_param_count;
1302 if (dst->flags & NETWORK_HAS_QOS_MASK)
1303 memcpy(&dst->qos_data, &src->qos_data,
1304 sizeof(struct ieee80211_qos_data));
1305 else {
1306 dst->qos_data.supported = src->qos_data.supported;
1307 dst->qos_data.param_count = src->qos_data.param_count;
1308 }
1309
1310 if (dst->qos_data.supported == 1) {
1311 if (dst->ssid_len)
1312 IEEE80211_DEBUG_QOS
1313 ("QoS the network %s is QoS supported\n",
1314 dst->ssid);
1315 else
1316 IEEE80211_DEBUG_QOS
1317 ("QoS the network is QoS supported\n");
1318 }
1319 dst->qos_data.active = qos_active;
1320 dst->qos_data.old_param_count = old_param;
1321
1029 /* dst->last_associate is not overwritten */ 1322 /* dst->last_associate is not overwritten */
1030} 1323}
1031 1324
@@ -1167,6 +1460,9 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1167 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n", 1460 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
1168 WLAN_FC_GET_STYPE(le16_to_cpu 1461 WLAN_FC_GET_STYPE(le16_to_cpu
1169 (header->frame_ctl))); 1462 (header->frame_ctl)));
1463 ieee80211_handle_assoc_resp(ieee,
1464 (struct ieee80211_assoc_response *)
1465 header, stats);
1170 break; 1466 break;
1171 1467
1172 case IEEE80211_STYPE_REASSOC_RESP: 1468 case IEEE80211_STYPE_REASSOC_RESP:
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index e9efdd42ba37..aba72f9880a1 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -465,7 +465,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
465 dev_kfree_skb_any(skb); 465 dev_kfree_skb_any(skb);
466 466
467 if (txb) { 467 if (txb) {
468 int ret = (*ieee->hard_start_xmit) (txb, dev); 468 int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
469 if (ret == 0) { 469 if (ret == 0) {
470 stats->tx_packets++; 470 stats->tx_packets++;
471 stats->tx_bytes += txb->payload_size; 471 stats->tx_bytes += txb->payload_size;
@@ -500,6 +500,7 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
500 unsigned long flags; 500 unsigned long flags;
501 struct net_device_stats *stats = &ieee->stats; 501 struct net_device_stats *stats = &ieee->stats;
502 struct sk_buff *skb_frag; 502 struct sk_buff *skb_frag;
503 int priority = -1;
503 504
504 spin_lock_irqsave(&ieee->lock, flags); 505 spin_lock_irqsave(&ieee->lock, flags);
505 506
@@ -540,7 +541,7 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
540 spin_unlock_irqrestore(&ieee->lock, flags); 541 spin_unlock_irqrestore(&ieee->lock, flags);
541 542
542 if (txb) { 543 if (txb) {
543 if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) { 544 if ((*ieee->hard_start_xmit) (txb, ieee->dev, priority) == 0) {
544 stats->tx_packets++; 545 stats->tx_packets++;
545 stats->tx_bytes += txb->payload_size; 546 stats->tx_bytes += txb->payload_size;
546 return 0; 547 return 0;