From 92ab85354993ac3a364c65cab45745af470ffc67 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 24 Jul 2008 21:02:04 +0300 Subject: mac80211: add ieee80211_queue_stopped) This patch adds ieee80211_queue_stopped that let drivers to query queue status Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/util.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0d463c80c404..24400618190c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -386,6 +386,13 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_stop_queues); +int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) +{ + struct ieee80211_local *local = hw_to_local(hw); + return __netif_subqueue_stopped(local->mdev, queue); +} +EXPORT_SYMBOL(ieee80211_queue_stopped); + void ieee80211_wake_queues(struct ieee80211_hw *hw) { int i; -- cgit v1.2.3 From b4f28bbb9bf0b2c829ecf97ce2173f204fde4f10 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 30 Jul 2008 17:19:55 +0200 Subject: mac80211: add rx status flag for short preamble and use it for the radiotap header Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 ++ net/mac80211/rx.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'net/mac80211') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 25cc192cbe4c..dcc05a197dc1 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -363,6 +363,7 @@ static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field) * is valid. This is useful in monitor mode and necessary for beacon frames * to enable IBSS merging. + * @RX_FLAG_SHORTPRE: Short preamble was used for this frame */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = 1<<0, @@ -373,6 +374,7 @@ enum mac80211_rx_flags { RX_FLAG_FAILED_FCS_CRC = 1<<5, RX_FLAG_FAILED_PLCP_CRC = 1<<6, RX_FLAG_TSFT = 1<<7, + RX_FLAG_SHORTPRE = 1<<8 }; /** diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6db854505193..ad47a614a202 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -143,6 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, /* IEEE80211_RADIOTAP_FLAGS */ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) *pos |= IEEE80211_RADIOTAP_F_FCS; + if (status->flag & RX_FLAG_SHORTPRE) + *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; pos++; /* IEEE80211_RADIOTAP_RATE */ -- cgit v1.2.3 From 9deb1ae572364a37d054d916c5bae858f91a3f9a Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 30 Jul 2008 17:20:06 +0200 Subject: mac80211: radiotap: assume modulation from rates use the rates ERP flag to derive CCK or OFDM modulation for the radiotap header. (it might be more correct to get this information from the hardware itself, but it seems safe to assume this in most practical cases.) Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- net/mac80211/rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ad47a614a202..60e9ea11115f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -157,8 +157,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, if (status->band == IEEE80211_BAND_5GHZ) *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ); + else if (rate->flags & IEEE80211_RATE_ERP_G) + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_2GHZ); else - *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN | + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); pos += 2; -- cgit v1.2.3 From 62bf1d762e24006fa9b6c8d56a22cf47a2310af3 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:05 -0700 Subject: mac80211: explicitly check skb->len ieee80211_get_hdrlen_from_skb internally checks the skb is long enough to hold the full ieee80211_hdr, else it returns zero. Use ieee80211_hdrlen which always returns the hdrlen and check the remaining room in the skb explicitly when removing encryption headers or the qos control field. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/main.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index aa5a191598c9..f5537f90dd36 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1244,9 +1244,10 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, struct ieee80211_key *key, struct sk_buff *skb) { - int hdrlen, iv_len, mic_len; + unsigned int hdrlen, iv_len, mic_len; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (!key) goto no_key; @@ -1268,24 +1269,20 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, goto no_key; } - if (skb->len >= mic_len && + if (skb->len >= hdrlen + mic_len && !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) skb_trim(skb, skb->len - mic_len); - if (skb->len >= iv_len && skb->len > hdrlen) { + if (skb->len >= hdrlen + iv_len) { memmove(skb->data + iv_len, skb->data, hdrlen); - skb_pull(skb, iv_len); + hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); } no_key: - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { - fc &= ~IEEE80211_STYPE_QOS_DATA; - hdr->frame_control = cpu_to_le16(fc); - memmove(skb->data + 2, skb->data, hdrlen - 2); - skb_pull(skb, 2); - } + if (ieee80211_is_data_qos(hdr->frame_control)) { + hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); + memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, + hdrlen - IEEE80211_QOS_CTL_LEN); + skb_pull(skb, IEEE80211_QOS_CTL_LEN); } } -- cgit v1.2.3 From c44d040e186e1af9d947f7bad886b7c1d35a22f6 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:07 -0700 Subject: mac80211: wme.h remove unused QOS_CONTROL_LEN linux/ieee80211.h now has IEEE80211_QOS_CTL_LEN for this purpose. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/wme.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 04de28c071a6..465e274df7c5 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h @@ -14,8 +14,6 @@ #include #include "ieee80211_i.h" -#define QOS_CONTROL_LEN 2 - #define QOS_CONTROL_ACK_POLICY_NORMAL 0 #define QOS_CONTROL_ACK_POLICY_NOACK 1 -- cgit v1.2.3 From d298487260d01934a8df3a4a2a09513d84a8e69b Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:10 -0700 Subject: mac80211: wep.c replace magic numbers in IV/ICV removal Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/wep.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 5c2bf0a3d4db..639998775b48 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -228,11 +228,10 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, return -1; hdrlen = ieee80211_hdrlen(hdr->frame_control); - - if (skb->len < 8 + hdrlen) + if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) return -1; - len = skb->len - hdrlen - 8; + len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; keyidx = skb->data[hdrlen + 3] >> 6; @@ -303,7 +302,7 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); /* remove ICV */ - skb_trim(rx->skb, rx->skb->len - 4); + skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); } return RX_CONTINUE; -- cgit v1.2.3 From b73d70ad8665fd3f35c855075b9a94de3e2b69e2 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:12 -0700 Subject: mac80211: rx.c/tx.c remove more users of tx/rx_data->fc Those functions that still use ieee80211_get_hdrlen are moved over to use the little endian frame control. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/rx.c | 62 +++++++++++++++++++++---------------------------------- net/mac80211/tx.c | 2 +- 2 files changed, 25 insertions(+), 39 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 60e9ea11115f..4e9631c140a3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -821,7 +821,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, static inline struct ieee80211_fragment_entry * ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, - u16 fc, unsigned int frag, unsigned int seq, + unsigned int frag, unsigned int seq, int rx_queue, struct ieee80211_hdr *hdr) { struct ieee80211_fragment_entry *entry; @@ -830,7 +830,6 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, idx = sdata->fragment_next; for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { struct ieee80211_hdr *f_hdr; - u16 f_fc; idx--; if (idx < 0) @@ -842,10 +841,13 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, entry->last_frag + 1 != frag) continue; - f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data; - f_fc = le16_to_cpu(f_hdr->frame_control); + f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; - if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) || + /* + * Check ftype and addresses are equal, else check next fragment + */ + if (((hdr->frame_control ^ f_hdr->frame_control) & + cpu_to_le16(IEEE80211_FCTL_FTYPE)) || compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) continue; @@ -870,11 +872,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) struct sk_buff *skb; DECLARE_MAC_BUF(mac); - hdr = (struct ieee80211_hdr *) rx->skb->data; + hdr = (struct ieee80211_hdr *)rx->skb->data; sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; - if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) || + if (likely((!ieee80211_has_morefrags(hdr->frame_control) && frag == 0) || (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ @@ -889,7 +891,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->queue, &(rx->skb)); if (rx->key && rx->key->conf.alg == ALG_CCMP && - (rx->fc & IEEE80211_FCTL_PROTECTED)) { + ieee80211_has_protected(hdr->frame_control)) { /* Store CCMP PN so that we can verify that the next * fragment has a sequential PN value. */ entry->ccmp = 1; @@ -903,8 +905,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) /* This is a fragment for a frame that should already be pending in * fragment cache. Add this fragment to the end of the pending entry. */ - entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq, - rx->queue, hdr); + entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); if (!entry) { I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); return RX_DROP_MONITOR; @@ -929,7 +930,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) memcpy(entry->last_pn, pn, CCMP_PN_LEN); } - skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc)); + skb_pull(rx->skb, ieee80211_hdrlen(hdr->frame_control)); __skb_queue_tail(&entry->skb_list, rx->skb); entry->last_frag = frag; entry->extra_len += rx->skb->len; @@ -1096,7 +1097,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - u16 fc, hdrlen, ethertype; + u16 hdrlen, ethertype; u8 *payload; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN] __aligned(2); @@ -1107,12 +1108,10 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) DECLARE_MAC_BUF(mac3); DECLARE_MAC_BUF(mac4); - fc = rx->fc; - - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) return -1; - hdrlen = ieee80211_get_hdrlen(fc); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (ieee80211_vif_is_mesh(&sdata->vif)) hdrlen += ieee80211_get_mesh_hdrlen( @@ -1127,41 +1126,28 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) * 1 0 BSSID SA DA n/a * 1 1 RA TA DA SA */ + memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); + memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); - switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { - case IEEE80211_FCTL_TODS: - /* BSSID SA DA */ - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - + switch (hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { + case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP && sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) return -1; break; - case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - /* RA TA DA SA */ - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - - if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && + case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): + if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) return -1; break; - case IEEE80211_FCTL_FROMDS: - /* DA BSSID SA */ - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - + case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): if (sdata->vif.type != IEEE80211_IF_TYPE_STA || (is_multicast_ether_addr(dst) && !compare_ether_addr(src, dev->dev_addr))) return -1; break; - case 0: - /* DA SA BSSID */ - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - + case __constant_cpu_to_le16(0): if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return -1; break; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4788f7b91f49..24146f3387a7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1025,7 +1025,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - hdrlen = ieee80211_get_hdrlen(tx->fc); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; tx->ethertype = (pos[0] << 8) | pos[1]; -- cgit v1.2.3 From 6b644e524bbd4089a28e0711de4f1cf2daa5db50 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:12 -0700 Subject: mac80211: remove ieee80211_get_hdrlen All users have been moved over to the version taking a le16 frame control rather than a cpu-endian value. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- include/net/mac80211.h | 10 ---------- net/mac80211/util.c | 39 --------------------------------------- 2 files changed, 49 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index dcc05a197dc1..0fdc3dabc964 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1558,16 +1558,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); */ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); -/** - * ieee80211_get_hdrlen - get header length from frame control - * - * This function returns the 802.11 header length in bytes (not including - * encryption headers.) - * - * @fc: the frame control field (in CPU endianness) - */ -int ieee80211_get_hdrlen(u16 fc); - /** * ieee80211_hdrlen - get header length in bytes from frame control * @fc: frame control field in little-endian format diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 24400618190c..f40c060341ae 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -91,45 +91,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, return NULL; } -int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (fc & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = 30; /* Addr4 */ - /* - * The QoS Control field is two bytes and its presence is - * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to - * hdrlen if that bit is set. - * This works by masking out the bit and shifting it to - * bit position 1 so the result has the value 0 or 2. - */ - hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) - >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1); - break; - case IEEE80211_FTYPE_CTL: - /* - * ACK and CTS are 10 bytes, all others 16. To see how - * to get this condition consider - * subtype mask: 0b0000000011110000 (0x00F0) - * ACK subtype: 0b0000000011010000 (0x00D0) - * CTS subtype: 0b0000000011000000 (0x00C0) - * bits that matter: ^^^ (0x00E0) - * value of those: 0b0000000011000000 (0x00C0) - */ - if ((fc & 0xE0) == 0xC0) - hdrlen = 10; - else - hdrlen = 16; - break; - } - - return hdrlen; -} -EXPORT_SYMBOL(ieee80211_get_hdrlen); - unsigned int ieee80211_hdrlen(__le16 fc) { unsigned int hdrlen = 24; -- cgit v1.2.3 From e7827a7031a931c74c48e4a53f73ed862f0c8da0 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:13 -0700 Subject: mac80211: remove IEEE80211_FC helper Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 -- net/mac80211/mesh_hwmp.c | 8 ++++---- net/mac80211/mesh_plink.c | 4 ++-- net/mac80211/mlme.c | 46 +++++++++++++++++++++++----------------------- net/mac80211/tx.c | 4 ++-- 5 files changed, 31 insertions(+), 33 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ec59345af65b..a2870bc245d9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -38,8 +38,6 @@ #define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08) -#define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype) - struct ieee80211_local; /* Maximum number of broadcast/multicast frames to buffer when some of the diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 08aca446ca01..2cdbd522631b 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -99,8 +99,8 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); @@ -178,8 +178,8 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, ra, ETH_ALEN); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9efeb1f07025..4a7e6d094ff9 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -163,8 +163,8 @@ static int mesh_plink_frame_tx(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1e97fb9fb34b..ac776c9d48fa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -641,8 +641,8 @@ static void ieee80211_send_auth(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); memset(mgmt, 0, 24 + 6); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_AUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_AUTH); if (encrypt) mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); @@ -771,8 +771,8 @@ static void ieee80211_send_assoc(struct net_device *dev, if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { skb_put(skb, 10); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_REASSOC_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_REASSOC_REQ); mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); @@ -780,8 +780,8 @@ static void ieee80211_send_assoc(struct net_device *dev, ETH_ALEN); } else { skb_put(skb, 4); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ASSOC_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ASSOC_REQ); mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); @@ -931,8 +931,8 @@ static void ieee80211_send_deauth(struct net_device *dev, memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_DEAUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DEAUTH); skb_put(skb, 2); mgmt->u.deauth.reason_code = cpu_to_le16(reason); @@ -960,8 +960,8 @@ static void ieee80211_send_disassoc(struct net_device *dev, memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_DISASSOC); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DISASSOC); skb_put(skb, 2); mgmt->u.disassoc.reason_code = cpu_to_le16(reason); @@ -1115,8 +1115,8 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_PROBE_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_REQ); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); if (dst) { memcpy(mgmt->da, dst, ETH_ALEN); @@ -1219,8 +1219,8 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); mgmt->u.action.category = WLAN_CATEGORY_BACK; @@ -1268,8 +1268,8 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); @@ -1524,8 +1524,8 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); @@ -1556,8 +1556,8 @@ void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) skb_reserve(skb, local->hw.extra_tx_headroom); bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); memset(bar, 0, sizeof(*bar)); - bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, - IEEE80211_STYPE_BACK_REQ); + bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_BACK_REQ); memcpy(bar->ra, ra, ETH_ALEN); memcpy(bar->ta, dev->dev_addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; @@ -1801,7 +1801,7 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, memcpy(msr_report->da, da, ETH_ALEN); memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); memcpy(msr_report->bssid, bssid, ETH_ALEN); - msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, + msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); @@ -2446,8 +2446,8 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_PROBE_RESP); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 24146f3387a7..9c60dedc3687 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1889,8 +1889,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, goto out; hdr = (struct ieee80211_hdr *) skb->data; - hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_BEACON); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_BEACON); num_beacons = &ifsta->num_beacons; } else if (ieee80211_vif_is_mesh(&sdata->vif)) { -- cgit v1.2.3 From 358c8d9d332230b14e130b78a6930996cdbf84c2 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:13 -0700 Subject: mac80211: use ieee80211 frame control directly Remove the last users of the rx/tx_data->fc data members and use the le16 frame_control from the header directly. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/rx.c | 53 ++++++++++++++++++++++++++--------------------------- net/mac80211/tx.c | 35 ++++++++++++++--------------------- net/mac80211/wep.c | 7 ++++--- 3 files changed, 44 insertions(+), 51 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4e9631c140a3..3a96251379f9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -867,16 +867,18 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) { struct ieee80211_hdr *hdr; u16 sc; + __le16 fc; unsigned int frag, seq; struct ieee80211_fragment_entry *entry; struct sk_buff *skb; DECLARE_MAC_BUF(mac); hdr = (struct ieee80211_hdr *)rx->skb->data; + fc = hdr->frame_control; sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; - if (likely((!ieee80211_has_morefrags(hdr->frame_control) && frag == 0) || + if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ @@ -891,7 +893,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->queue, &(rx->skb)); if (rx->key && rx->key->conf.alg == ALG_CCMP && - ieee80211_has_protected(hdr->frame_control)) { + ieee80211_has_protected(fc)) { /* Store CCMP PN so that we can verify that the next * fragment has a sequential PN value. */ entry->ccmp = 1; @@ -930,11 +932,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) memcpy(entry->last_pn, pn, CCMP_PN_LEN); } - skb_pull(rx->skb, ieee80211_hdrlen(hdr->frame_control)); + skb_pull(rx->skb, ieee80211_hdrlen(fc)); __skb_queue_tail(&entry->skb_list, rx->skb); entry->last_frag = frag; entry->extra_len += rx->skb->len; - if (rx->fc & IEEE80211_FCTL_MOREFRAGS) { + if (ieee80211_has_morefrags(fc)) { rx->skb = NULL; return RX_QUEUED; } @@ -974,10 +976,9 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) struct sk_buff *skb; int no_pending_pkts; DECLARE_MAC_BUF(mac); + __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; - if (likely(!rx->sta || - (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL || - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL || + if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || !(rx->flags & IEEE80211_RX_RA_MATCH))) return RX_CONTINUE; @@ -1073,7 +1074,7 @@ ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) } static int -ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) +ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) { /* * Pass through unencrypted frames if the hardware has @@ -1083,9 +1084,8 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) return 0; /* Drop unencrypted frames if key is set. */ - if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && - (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && + if (unlikely(!ieee80211_has_protected(fc) && + !ieee80211_is_nullfunc(fc) && (rx->key || rx->sdata->drop_unencrypted))) return -EACCES; @@ -1184,7 +1184,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) /* * requires that rx->skb is a frame with ethernet header */ -static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) +static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) { static const u8 pae_group_addr[ETH_ALEN] __aligned(2) = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; @@ -1200,7 +1200,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) return true; if (ieee80211_802_1x_port_control(rx) || - ieee80211_drop_unencrypted(rx)) + ieee80211_drop_unencrypted(rx, fc)) return false; return true; @@ -1270,20 +1270,21 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; struct ieee80211_local *local = rx->local; - u16 fc, ethertype; + u16 ethertype; u8 *payload; struct sk_buff *skb = rx->skb, *frame = NULL; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + __le16 fc = hdr->frame_control; const struct ethhdr *eth; int remaining, err; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; DECLARE_MAC_BUF(mac); - fc = rx->fc; - if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) + if (unlikely(!ieee80211_is_data(fc))) return RX_CONTINUE; - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) + if (unlikely(!ieee80211_is_data_present(fc))) return RX_DROP_MONITOR; if (!(rx->flags & IEEE80211_RX_AMSDU)) @@ -1365,7 +1366,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); } - if (!ieee80211_frame_allowed(rx)) { + if (!ieee80211_frame_allowed(rx, fc)) { if (skb == frame) /* last frame */ return RX_DROP_UNUSABLE; dev_kfree_skb(frame); @@ -1439,21 +1440,21 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_data(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->dev; - u16 fc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + __le16 fc = hdr->frame_control; int err; - fc = rx->fc; - if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) + if (unlikely(!ieee80211_is_data(hdr->frame_control))) return RX_CONTINUE; - if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) + if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) return RX_DROP_MONITOR; err = ieee80211_data_to_8023(rx); if (unlikely(err)) return RX_DROP_UNUSABLE; - if (!ieee80211_frame_allowed(rx)) + if (!ieee80211_frame_allowed(rx, fc)) return RX_DROP_MONITOR; rx->skb->dev = dev; @@ -1818,13 +1819,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata; struct ieee80211_hdr *hdr; struct ieee80211_rx_data rx; - u16 type; int prepares; struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; u8 *bssid; - hdr = (struct ieee80211_hdr *) skb->data; + hdr = (struct ieee80211_hdr *)skb->data; memset(&rx, 0, sizeof(rx)); rx.skb = skb; rx.local = local; @@ -1832,9 +1832,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.status = status; rx.rate = rate; rx.fc = le16_to_cpu(hdr->frame_control); - type = rx.fc & IEEE80211_FCTL_FTYPE; - if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) + if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) local->dot11ReceivedFragmentCount++; rx.sta = sta_info_get(local, hdr->addr2); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9c60dedc3687..96ffb4d8dfbb 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -82,6 +82,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, struct ieee80211_rate *txrate; struct ieee80211_local *local = tx->local; struct ieee80211_supported_band *sband; + struct ieee80211_hdr *hdr; sband = local->hw.wiphy->bands[tx->channel->band]; txrate = &sband->bitrates[tx->rate_idx]; @@ -107,8 +108,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, * at the highest possible rate belonging to the PHY rates in the * BSSBasicRateSet */ - - if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) { + hdr = (struct ieee80211_hdr *)tx->skb->data; + if (ieee80211_is_ctl(hdr->frame_control)) { /* TODO: These control frames are not currently sent by * 80211.o, but should they be implemented, this function * needs to be updated to support duration field calculation. @@ -213,9 +214,8 @@ static int inline is_ieee80211_device(struct net_device *dev, static ieee80211_tx_result debug_noinline ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) { -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); u32 sta_flags; @@ -223,8 +223,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) return TX_CONTINUE; if (unlikely(tx->local->sta_sw_scanning) && - ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || - (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ)) + !ieee80211_is_probe_req(hdr->frame_control)) return TX_DROP; if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) @@ -238,7 +237,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (likely(tx->flags & IEEE80211_TX_UNICAST)) { if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { + ieee80211_is_data(hdr->frame_control))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "%s: dropped data frame to not " @@ -249,7 +248,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) return TX_DROP; } } else { - if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && + if (unlikely(ieee80211_is_data(hdr->frame_control) && tx->local->num_sta == 0 && tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) { /* @@ -315,6 +314,7 @@ static ieee80211_tx_result ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; /* * broadcast/multicast frame @@ -329,7 +329,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) return TX_CONTINUE; /* no buffering for ordered frames */ - if (tx->fc & IEEE80211_FCTL_ORDER) + if (ieee80211_has_order(hdr->frame_control)) return TX_CONTINUE; /* no stations in PS mode */ @@ -367,12 +367,11 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) { struct sta_info *sta = tx->sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; u32 staflags; DECLARE_MAC_BUF(mac); - if (unlikely(!sta || - ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && - (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) + if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) return TX_CONTINUE; staflags = get_sta_flags(sta); @@ -437,7 +436,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) { struct ieee80211_key *key; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - u16 fc = tx->fc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; if (unlikely(tx->skb->do_not_encrypt)) tx->key = NULL; @@ -454,22 +453,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key = NULL; if (tx->key) { - u16 ftype, stype; - tx->key->tx_rx_count++; /* TODO: add threshold stuff again */ switch (tx->key->conf.alg) { case ALG_WEP: - ftype = fc & IEEE80211_FCTL_FTYPE; - stype = fc & IEEE80211_FCTL_STYPE; - - if (ftype == IEEE80211_FTYPE_MGMT && - stype == IEEE80211_STYPE_AUTH) + if (ieee80211_is_auth(hdr->frame_control)) break; case ALG_TKIP: case ALG_CCMP: - if (!WLAN_FC_DATA_PRESENT(fc)) + if (!ieee80211_is_data_present(hdr->frame_control)) tx->key = NULL; break; } diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 639998775b48..376c84987e4f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -291,9 +291,10 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) ieee80211_rx_result ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) { - if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && - ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + + if (!ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) return RX_CONTINUE; if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { -- cgit v1.2.3 From a4b7d7bda566acaa65fbf767f65a83b3a8dc74b9 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:14 -0700 Subject: mac80211: remove rx/tx_data->fc member Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/rx.c | 8 ++------ net/mac80211/tx.c | 1 - 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a2870bc245d9..978c3a03ea57 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -172,7 +172,7 @@ struct ieee80211_tx_data { struct sk_buff **extra_frag; int num_extra_frag; - u16 fc, ethertype; + u16 ethertype; unsigned int flags; }; @@ -200,7 +200,7 @@ struct ieee80211_rx_data { struct ieee80211_rx_status *status; struct ieee80211_rate *rate; - u16 fc, ethertype; + u16 ethertype; unsigned int flags; int sent_ps_buffered; int queue; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3a96251379f9..2464263cb7a5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1057,7 +1057,6 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); /* change frame type to non QOS */ - rx->fc &= ~IEEE80211_STYPE_QOS_DATA; hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); return RX_CONTINUE; @@ -1831,7 +1830,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, rx.status = status; rx.rate = rate; - rx.fc = le16_to_cpu(hdr->frame_control); if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) local->dot11ReceivedFragmentCount++; @@ -1894,14 +1892,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, prev->dev->name); continue; } - rx.fc = le16_to_cpu(hdr->frame_control); ieee80211_invoke_rx_handlers(prev, &rx, skb_new); prev = sdata; } - if (prev) { - rx.fc = le16_to_cpu(hdr->frame_control); + if (prev) ieee80211_invoke_rx_handlers(prev, &rx, skb); - } else + else dev_kfree_skb(skb); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 96ffb4d8dfbb..85f3ba85c132 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -993,7 +993,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, hdr = (struct ieee80211_hdr *) skb->data; tx->sta = sta_info_get(local, hdr->addr1); - tx->fc = le16_to_cpu(hdr->frame_control); if (is_multicast_ether_addr(hdr->addr1)) { tx->flags &= ~IEEE80211_TX_UNICAST; -- cgit v1.2.3 From 4eb2ae9a42b77de48ee9fecfaccc66c640313188 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Tue, 15 Jul 2008 18:44:15 -0700 Subject: mac80211: remove WLAN_FC_DATA_PRESENT All users are gone now. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 978c3a03ea57..3cad0172b45e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -36,8 +36,6 @@ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #endif /* ETH_P_PAE */ -#define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08) - struct ieee80211_local; /* Maximum number of broadcast/multicast frames to buffer when some of the -- cgit v1.2.3 From bdbe819540f3365249095692118dbfeee308140d Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Thu, 14 Aug 2008 10:40:48 -0700 Subject: mac80211: allow no mac address until firmware load Originally by Johannes Berg. This patch adds support for devices that do not report their MAC address until the firmware is loaded. While the address is not known, a multicast on is used. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville --- net/mac80211/main.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f5537f90dd36..93dcdc27254b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -187,9 +187,15 @@ static int ieee80211_open(struct net_device *dev) u32 changed = 0; int res; bool need_hw_reconfig = 0; + u8 null_addr[ETH_ALEN] = {0}; sdata = IEEE80211_DEV_TO_SUB_IF(dev); + /* fail early if user set an invalid address */ + if (compare_ether_addr(dev->dev_addr, null_addr) && + !is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + /* we hold the RTNL here so can safely walk the list */ list_for_each_entry(nsdata, &local->interfaces, list) { struct net_device *ndev = nsdata->dev; @@ -270,6 +276,36 @@ static int ieee80211_open(struct net_device *dev) ieee80211_led_radio(local, local->hw.conf.radio_enabled); } + /* + * Check all interfaces and copy the hopefully now-present + * MAC address to those that have the special null one. + */ + list_for_each_entry(nsdata, &local->interfaces, list) { + struct net_device *ndev = nsdata->dev; + + /* + * No need to check netif_running since we do not allow + * it to start up with this invalid address. + */ + if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) + memcpy(ndev->dev_addr, + local->hw.wiphy->perm_addr, + ETH_ALEN); + } + + if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) + memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, + ETH_ALEN); + + /* + * Validate the MAC address for this device. + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + if (!local->open_count && local->ops->stop) + local->ops->stop(local_to_hw(local)); + return -EADDRNOTAVAIL; + } + switch (sdata->vif.type) { case IEEE80211_IF_TYPE_VLAN: /* no need to tell driver */ @@ -975,6 +1011,8 @@ void ieee80211_if_setup(struct net_device *dev) dev->open = ieee80211_open; dev->stop = ieee80211_stop; dev->destructor = free_netdev; + /* we will validate the address ourselves in ->open */ + dev->validate_addr = NULL; } /* everything else */ -- cgit v1.2.3 From fef1643bf0cdd092a52dc3378479e4811fd65152 Mon Sep 17 00:00:00 2001 From: Jasper Bryant-Greene Date: Sun, 3 Aug 2008 11:30:55 +1200 Subject: move ETH_P_PAE from ieee80211_i.h to if_ether.h ETH_P_PAE belongs in if_ether.h with the other ETH_P_* definitions. This patch moves it there. Signed-off-by: Jasper Bryant-Greene Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/if_ether.h | 1 + net/mac80211/ieee80211_i.h | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index e157c1399b61..5028e0b6082b 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -74,6 +74,7 @@ #define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport * over Ethernet */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ #define ETH_P_TIPC 0x88CA /* TIPC */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3cad0172b45e..168f845c1737 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -32,10 +32,6 @@ /* ieee80211.o internal definitions, etc. These are not included into * low-level drivers. */ -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - struct ieee80211_local; /* Maximum number of broadcast/multicast frames to buffer when some of the -- cgit v1.2.3 From f698d856f65c3fea091cc303a135967965c5b880 Mon Sep 17 00:00:00 2001 From: Jasper Bryant-Greene Date: Sun, 3 Aug 2008 12:04:37 +1200 Subject: replace net_device arguments with ieee80211_{local,sub_if_data} as appropriate This patch replaces net_device arguments to mac80211 internal functions with ieee80211_{local,sub_if_data} as appropriate. It also does the same for many 802.11s mesh functions, and changes the mesh path table to be indexed on sub_if_data rather than net_device. If the mesh part needs to be a separate patch let me know, but since mesh uses a lot of mac80211 functions which were being converted anyway, the changes go hand-in-hand somewhat. This patch probably does not convert all the functions which could be converted, but it is a large chunk and followup patches will be provided. Signed-off-by: Jasper Bryant-Greene Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 21 +- net/mac80211/debugfs_sta.c | 2 +- net/mac80211/event.c | 5 +- net/mac80211/ieee80211_i.h | 48 ++-- net/mac80211/iface.c | 8 +- net/mac80211/main.c | 16 +- net/mac80211/mesh.c | 29 +- net/mac80211/mesh.h | 61 +++-- net/mac80211/mesh_hwmp.c | 112 ++++---- net/mac80211/mesh_pathtbl.c | 76 +++--- net/mac80211/mesh_plink.c | 52 ++-- net/mac80211/mlme.c | 652 ++++++++++++++++++++------------------------ net/mac80211/rx.c | 16 +- net/mac80211/tx.c | 4 +- net/mac80211/wext.c | 49 ++-- net/mac80211/wpa.c | 2 +- 16 files changed, 545 insertions(+), 608 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 297c257864c7..6d2ad2bf3ab5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -66,13 +66,16 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) { struct net_device *dev; + struct ieee80211_sub_if_data *sdata; /* we're under RTNL */ dev = __dev_get_by_index(&init_net, ifindex); if (!dev) return -ENODEV; - ieee80211_if_remove(dev); + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + ieee80211_if_remove(sdata); return 0; } @@ -842,13 +845,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; } - err = mesh_path_add(dst, dev); + err = mesh_path_add(dst, sdata); if (err) { rcu_read_unlock(); return err; } - mpath = mesh_path_lookup(dst, dev); + mpath = mesh_path_lookup(dst, sdata); if (!mpath) { rcu_read_unlock(); return -ENXIO; @@ -862,10 +865,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst) { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (dst) - return mesh_path_del(dst, dev); + return mesh_path_del(dst, sdata); - mesh_path_flush(dev); + mesh_path_flush(sdata); return 0; } @@ -897,7 +902,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, return -ENOENT; } - mpath = mesh_path_lookup(dst, dev); + mpath = mesh_path_lookup(dst, sdata); if (!mpath) { rcu_read_unlock(); return -ENOENT; @@ -965,7 +970,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, return -ENOTSUPP; rcu_read_lock(); - mpath = mesh_path_lookup(dst, dev); + mpath = mesh_path_lookup(dst, sdata); if (!mpath) { rcu_read_unlock(); return -ENOENT; @@ -993,7 +998,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, return -ENOTSUPP; rcu_read_lock(); - mpath = mesh_path_lookup_by_idx(idx, dev); + mpath = mesh_path_lookup_by_idx(idx, sdata); if (!mpath) { rcu_read_unlock(); return -ENOENT; diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 79a062782d52..6abe5427752b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -201,7 +201,7 @@ static ssize_t sta_agg_status_write(struct file *file, tid_num = tid_num - 100; if (tid_static_rx[tid_num] == 1) { strcpy(state, "off "); - ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0, + ieee80211_sta_stop_rx_ba_session(sta->sdata, da, tid_num, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); sta->ampdu_mlme.tid_state_rx[tid_num] |= HT_AGG_STATE_DEBUGFS_CTL; diff --git a/net/mac80211/event.c b/net/mac80211/event.c index 2280f40b4560..8de60de70bc9 100644 --- a/net/mac80211/event.c +++ b/net/mac80211/event.c @@ -8,7 +8,6 @@ * mac80211 - events */ -#include #include #include "ieee80211_i.h" @@ -17,7 +16,7 @@ * (in the variable hdr) must be long enough to extract the TKIP * fields like TSC */ -void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, +void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr) { union iwreq_data wrqu; @@ -32,7 +31,7 @@ void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, print_mac(mac, hdr->addr2)); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = strlen(buf); - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); kfree(buf); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 168f845c1737..b5d3f58a7845 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -851,65 +851,65 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, /* ieee80211_ioctl.c */ extern const struct iw_handler_def ieee80211_iw_handler_def; -int ieee80211_set_freq(struct net_device *dev, int freq); +int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); /* ieee80211_sta.c */ void ieee80211_sta_timer(unsigned long data); void ieee80211_sta_work(struct work_struct *work); void ieee80211_sta_scan_work(struct work_struct *work); -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len); -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); -void ieee80211_sta_req_auth(struct net_device *dev, +int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); +int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); +int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); +void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); -int ieee80211_sta_scan_results(struct net_device *dev, +int ieee80211_sta_scan_results(struct ieee80211_local *local, struct iw_request_info *info, char *buf, size_t len); ieee80211_rx_result ieee80211_sta_rx_scan( - struct net_device *dev, struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); void ieee80211_rx_bss_list_init(struct ieee80211_local *local); void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); -struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); +struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates); -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); +int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); +int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); -u32 ieee80211_reset_erp_info(struct net_device *dev); +u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_ht_info *ht_info); int ieee80211_ht_addt_info_ie_to_ht_bss_info( struct ieee80211_ht_addt_info *ht_add_info_ie, struct ieee80211_ht_bss_info *bss_info); -void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, +void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u8 dialog_token, u16 start_seq_num, u16 agg_size, u16 timeout); -void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, +void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code); -void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn); +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); -void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u16 initiator, u16 reason); void sta_addba_resp_timer_expired(unsigned long data); -void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); u64 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); -void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); #ifdef CONFIG_MAC80211_MESH -void ieee80211_start_mesh(struct net_device *dev); +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); #else -static inline void ieee80211_start_mesh(struct net_device *dev) +static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) {} #endif @@ -920,7 +920,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct vif_params *params); int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, enum ieee80211_if_types type); -void ieee80211_if_remove(struct net_device *dev); +void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); /* tx handling */ @@ -938,7 +938,7 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum ieee80211_if_types type); int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, int rate, int erp, int short_preamble); -void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, +void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr); #ifdef CONFIG_MAC80211_NOINLINE diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 610ed1d9893a..4a623b8e91fd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -56,7 +56,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) case IEEE80211_IF_TYPE_MESH_POINT: /* Allow compiler to elide mesh_rmc_free call. */ if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rmc_free(dev); + mesh_rmc_free(sdata); /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: @@ -241,15 +241,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, return ret; } -void ieee80211_if_remove(struct net_device *dev) +void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ASSERT_RTNL(); list_del_rcu(&sdata->list); synchronize_rcu(); - unregister_netdevice(dev); + unregister_netdevice(sdata->dev); } /* diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 93dcdc27254b..819639486653 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -347,8 +347,8 @@ static int ieee80211_open(struct net_device *dev) goto err_stop; if (ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_start_mesh(sdata->dev); - changed |= ieee80211_reset_erp_info(dev); + ieee80211_start_mesh(sdata); + changed |= ieee80211_reset_erp_info(sdata); ieee80211_bss_info_change_notify(sdata, changed); ieee80211_enable_keys(sdata); @@ -448,7 +448,7 @@ static int ieee80211_stop(struct net_device *dev) list_for_each_entry_rcu(sta, &local->sta_list, list) { if (sta->sdata == sdata) - ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); + ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); } rcu_read_unlock(); @@ -706,7 +706,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; - ieee80211_send_addba_request(sta->sdata->dev, ra, tid, + ieee80211_send_addba_request(sta->sdata, ra, tid, sta->ampdu_mlme.tid_tx[tid]->dialog_token, sta->ampdu_mlme.tid_tx[tid]->ssn, 0x40, 5000); @@ -889,7 +889,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) } if (*state & HT_AGG_STATE_INITIATOR_MSK) - ieee80211_send_delba(sta->sdata->dev, ra, tid, + ieee80211_send_delba(sta->sdata, ra, tid, WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); agg_queue = sta->tid_to_tx_q[tid]; @@ -1200,10 +1200,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, changed); } -u32 ieee80211_reset_erp_info(struct net_device *dev) +u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - sdata->bss_conf.use_cts_prot = 0; sdata->bss_conf.use_short_preamble = 0; return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; @@ -1438,7 +1436,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) tid = qc[0] & 0xf; ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) & IEEE80211_SCTL_SEQ); - ieee80211_send_bar(sta->sdata->dev, hdr->addr1, + ieee80211_send_bar(sta->sdata, hdr->addr1, tid, ssn); } } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b5933b271491..b631703bcc82 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -39,14 +39,13 @@ void ieee80211s_stop(void) * mesh_matches_local - check if the config of a mesh point matches ours * * @ie: information elements of a management frame from the mesh peer - * @dev: local mesh interface + * @sdata: local mesh subif * * This function checks if the mesh configuration of a mesh point matches the * local mesh configuration, i.e. if both nodes belong to the same mesh network. */ -bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) +bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *sta = &sdata->u.sta; /* @@ -73,10 +72,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links * * @ie: information elements of a management frame from the mesh peer - * @dev: local mesh interface */ -bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, - struct net_device *dev) +bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) { return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; } @@ -111,9 +108,8 @@ void mesh_ids_set_default(struct ieee80211_if_sta *sta) memcpy(sta->mesh_cc_id, def_id, 4); } -int mesh_rmc_init(struct net_device *dev) +int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int i; sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); @@ -125,9 +121,8 @@ int mesh_rmc_init(struct net_device *dev) return 0; } -void mesh_rmc_free(struct net_device *dev) +void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_rmc *rmc = sdata->u.sta.rmc; struct rmc_entry *p, *n; int i; @@ -158,9 +153,8 @@ void mesh_rmc_free(struct net_device *dev) * it. */ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, - struct net_device *dev) + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_rmc *rmc = sdata->u.sta.rmc; u32 seqnum = 0; int entries = 0; @@ -194,10 +188,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, return 0; } -void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) +void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; u8 *pos; int len, i, rate; @@ -262,10 +255,10 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) return; } -u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl) +u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) { /* Use last four bytes of hw addr and interface index as hash index */ - return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd) + return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) & tbl->hash_mask; } @@ -434,7 +427,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ifsta->preq_id = 0; ifsta->dsn = 0; atomic_set(&ifsta->mpaths, 0); - mesh_rmc_init(sdata->dev); + mesh_rmc_init(sdata); ifsta->last_preq = jiffies; /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 7495fbb0d211..84ff5d828fdb 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -47,7 +47,7 @@ enum mesh_path_flags { * struct mesh_path - mac80211 mesh path structure * * @dst: mesh path destination mac address - * @dev: mesh path device + * @sdata: mesh subif * @next_hop: mesh neighbor to which frames for this destination will be * forwarded * @timer: mesh path discovery timer @@ -64,14 +64,14 @@ enum mesh_path_flags { * @state_lock: mesh pat state lock * * - * The combination of dst and dev is unique in the mesh path table. Since the + * The combination of dst and sdata is unique in the mesh path table. Since the * next_hop STA is only protected by RCU as well, deleting the STA must also * remove/substitute the mesh_path structure and wait until that is no longer * reachable before destroying the STA completely. */ struct mesh_path { u8 dst[ETH_ALEN]; - struct net_device *dev; + struct ieee80211_sub_if_data *sdata; struct sta_info *next_hop; struct timer_list timer; struct sk_buff_head frame_queue; @@ -203,59 +203,66 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, struct ieee80211_sub_if_data *sdata); int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, - struct net_device *dev); -bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev); + struct ieee80211_sub_if_data *sdata); +bool mesh_matches_local(struct ieee802_11_elems *ie, + struct ieee80211_sub_if_data *sdata); void mesh_ids_set_default(struct ieee80211_if_sta *sta); -void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev); -void mesh_rmc_free(struct net_device *dev); -int mesh_rmc_init(struct net_device *dev); +void mesh_mgmt_ies_add(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); +int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); void ieee80211s_stop(void); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ -int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); -void mesh_path_start_discovery(struct net_device *dev); -struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); -struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); +int mesh_nexthop_lookup(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); +void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); +struct mesh_path *mesh_path_lookup(u8 *dst, + struct ieee80211_sub_if_data *sdata); +struct mesh_path *mesh_path_lookup_by_idx(int idx, + struct ieee80211_sub_if_data *sdata); void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); -void mesh_path_expire(struct net_device *dev); -void mesh_path_flush(struct net_device *dev); -void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, - size_t len); -int mesh_path_add(u8 *dst, struct net_device *dev); +void mesh_path_expire(struct ieee80211_sub_if_data *sdata); +void mesh_path_flush(struct ieee80211_sub_if_data *sdata); +void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len); +int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); /* Mesh plinks */ -void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, - bool add); -bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, - struct net_device *dev); +void mesh_neighbour_update(u8 *hw_addr, u64 rates, + struct ieee80211_sub_if_data *sdata, bool add); +bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); void mesh_plink_deactivate(struct sta_info *sta); int mesh_plink_open(struct sta_info *sta); int mesh_plink_close(struct sta_info *sta); void mesh_plink_block(struct sta_info *sta); -void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, - size_t len, struct ieee80211_rx_status *rx_status); +void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len, + struct ieee80211_rx_status *rx_status); /* Private interfaces */ /* Mesh tables */ struct mesh_table *mesh_table_alloc(int size_order); void mesh_table_free(struct mesh_table *tbl, bool free_leafs); struct mesh_table *mesh_table_grow(struct mesh_table *tbl); -u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl); +u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, + struct mesh_table *tbl); /* Mesh paths */ int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, - struct net_device *dev); + struct ieee80211_sub_if_data *sdata); void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); void mesh_path_flush_pending(struct mesh_path *mpath); void mesh_path_tx_pending(struct mesh_path *mpath); int mesh_pathtbl_init(void); void mesh_pathtbl_unregister(void); -int mesh_path_del(u8 *addr, struct net_device *dev); +int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); void mesh_path_timer(unsigned long data); void mesh_path_flush_by_nexthop(struct sta_info *sta); -void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev); +void mesh_path_discard_frame(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata); #ifdef CONFIG_MAC80211_MESH extern int mesh_allocated; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 2cdbd522631b..eeb0ce2d5d37 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -82,9 +82,9 @@ enum mpath_frame_type { static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, - __le32 metric, __le32 preq_id, struct net_device *dev) + __le32 metric, __le32 preq_id, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; u8 *pos; @@ -103,7 +103,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = action; @@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return 0; } @@ -161,9 +161,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, * @ra: node this frame is addressed to */ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, - struct net_device *dev) + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; u8 *pos; @@ -182,7 +182,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, IEEE80211_STYPE_ACTION); memcpy(mgmt->da, ra, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; @@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return 0; } @@ -233,7 +233,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, /** * hwmp_route_info_get - Update routing info to originator and transmitter * - * @dev: local mesh interface + * @sdata: local mesh subif * @mgmt: mesh management frame * @hwmp_ie: hwmp information element (PREP or PREQ) * @@ -246,11 +246,11 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, * Notes: this function is the only place (besides user-provided info) where * path routing information is updated. */ -static u32 hwmp_route_info_get(struct net_device *dev, +static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *hwmp_ie) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct mesh_path *mpath; struct sta_info *sta; bool fresh_info; @@ -301,14 +301,14 @@ static u32 hwmp_route_info_get(struct net_device *dev, new_metric = MAX_METRIC; exp_time = TU_TO_EXP_TIME(orig_lifetime); - if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { /* This MP is the originator, we are not interested in this * frame, except for updating transmitter's path info. */ process = false; fresh_info = false; } else { - mpath = mesh_path_lookup(orig_addr, dev); + mpath = mesh_path_lookup(orig_addr, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_FIXED) @@ -324,8 +324,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, } } } else { - mesh_path_add(orig_addr, dev); - mpath = mesh_path_lookup(orig_addr, dev); + mesh_path_add(orig_addr, sdata); + mpath = mesh_path_lookup(orig_addr, sdata); if (!mpath) { rcu_read_unlock(); return 0; @@ -357,7 +357,7 @@ static u32 hwmp_route_info_get(struct net_device *dev, else { fresh_info = true; - mpath = mesh_path_lookup(ta, dev); + mpath = mesh_path_lookup(ta, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if ((mpath->flags & MESH_PATH_FIXED) || @@ -365,8 +365,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, (last_hop_metric > mpath->metric))) fresh_info = false; } else { - mesh_path_add(ta, dev); - mpath = mesh_path_lookup(ta, dev); + mesh_path_add(ta, sdata); + mpath = mesh_path_lookup(ta, sdata); if (!mpath) { rcu_read_unlock(); return 0; @@ -392,10 +392,9 @@ static u32 hwmp_route_info_get(struct net_device *dev, return process ? new_metric : 0; } -static void hwmp_preq_frame_process(struct net_device *dev, +static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct mesh_path *mpath; u8 *dst_addr, *orig_addr; @@ -411,7 +410,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); dst_flags = PREQ_IE_DST_F(preq_elem); - if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { forward = false; reply = true; metric = 0; @@ -423,7 +422,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, } } else { rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) { if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || DSN_LT(mpath->dsn, dst_dsn)) { @@ -451,7 +450,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, cpu_to_le32(dst_dsn), 0, orig_addr, cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), - 0, dev); + 0, sdata); else ifsta->mshstats.dropped_frames_ttl++; } @@ -472,20 +471,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, cpu_to_le32(orig_dsn), dst_flags, dst_addr, - cpu_to_le32(dst_dsn), dev->broadcast, + cpu_to_le32(dst_dsn), sdata->dev->broadcast, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), cpu_to_le32(preq_id), - dev); + sdata); ifsta->mshstats.fwded_frames++; } } -static void hwmp_prep_frame_process(struct net_device *dev, +static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_path *mpath; u8 *dst_addr, *orig_addr; u8 ttl, hopcount, flags; @@ -499,7 +497,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, * replies */ dst_addr = PREP_IE_DST_ADDR(prep_elem); - if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) /* destination, no forwarding required */ return; @@ -510,7 +508,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, } rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) spin_lock_bh(&mpath->state_lock); else @@ -533,7 +531,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, cpu_to_le32(orig_dsn), 0, dst_addr, cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), - 0, dev); + 0, sdata); rcu_read_unlock(); sdata->u.sta.mshstats.fwded_frames++; return; @@ -544,7 +542,7 @@ fail: return; } -static void hwmp_perr_frame_process(struct net_device *dev, +static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *perr_elem) { struct mesh_path *mpath; @@ -555,7 +553,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, dst_addr = PERR_IE_DST_ADDR(perr_elem); dst_dsn = PERR_IE_DST_DSN(perr_elem); rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_ACTIVE && @@ -566,7 +564,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, mpath->dsn = dst_dsn; spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), - dev->broadcast, dev); + sdata->dev->broadcast, sdata); } else spin_unlock_bh(&mpath->state_lock); } @@ -575,7 +573,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, -void mesh_rx_path_sel_frame(struct net_device *dev, +void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -592,25 +590,25 @@ void mesh_rx_path_sel_frame(struct net_device *dev, if (!elems.preq || elems.preq_len != 37) /* Right now we support just 1 destination and no AE */ return; - last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq); + last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq); if (!last_hop_metric) return; - hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric); + hwmp_preq_frame_process(sdata, mgmt, elems.preq, last_hop_metric); break; case MPATH_PREP: if (!elems.prep || elems.prep_len != 31) /* Right now we support no AE */ return; - last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep); + last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep); if (!last_hop_metric) return; - hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric); + hwmp_prep_frame_process(sdata, mgmt, elems.prep, last_hop_metric); break; case MPATH_PERR: if (!elems.perr || elems.perr_len != 12) /* Right now we support only one destination per PERR */ return; - hwmp_perr_frame_process(dev, mgmt, elems.perr); + hwmp_perr_frame_process(sdata, mgmt, elems.perr); default: return; } @@ -628,8 +626,7 @@ void mesh_rx_path_sel_frame(struct net_device *dev, */ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(mpath->dev); + struct ieee80211_sub_if_data *sdata = mpath->sdata; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct mesh_preq_queue *preq_node; @@ -672,12 +669,10 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) /** * mesh_path_start_discovery - launch a path discovery from the PREQ queue * - * @dev: local mesh interface + * @sdata: local mesh subif */ -void mesh_path_start_discovery(struct net_device *dev) +void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct mesh_preq_queue *preq_node; struct mesh_path *mpath; @@ -699,7 +694,7 @@ void mesh_path_start_discovery(struct net_device *dev) spin_unlock(&ifsta->mesh_preq_queue_lock); rcu_read_lock(); - mpath = mesh_path_lookup(preq_node->dst, dev); + mpath = mesh_path_lookup(preq_node->dst, sdata); if (!mpath) goto enddiscovery; @@ -743,11 +738,11 @@ void mesh_path_start_discovery(struct net_device *dev) dst_flags = MP_F_RF; spin_unlock_bh(&mpath->state_lock); - mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr, + mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, - cpu_to_le32(mpath->dsn), dev->broadcast, 0, + cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, ttl, cpu_to_le32(lifetime), 0, - cpu_to_le32(ifsta->preq_id++), dev); + cpu_to_le32(ifsta->preq_id++), sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: @@ -759,7 +754,7 @@ enddiscovery: * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame * * @skb: 802.11 frame to be sent - * @dev: network device the frame will be sent through + * @sdata: network subif the frame will be sent through * @fwd_frame: true if this frame was originally from a different host * * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is @@ -767,9 +762,9 @@ enddiscovery: * sent when the path is resolved. This means the caller must not free the skb * in this case. */ -int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) +int mesh_nexthop_lookup(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sk_buff *skb_to_free = NULL; struct mesh_path *mpath; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; @@ -777,11 +772,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) int err = 0; rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { - mesh_path_add(dst_addr, dev); - mpath = mesh_path_lookup(dst_addr, dev); + mesh_path_add(dst_addr, sdata); + mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { dev_kfree_skb(skb); sdata->u.sta.mshstats.dropped_frames_no_route++; @@ -793,7 +788,8 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, mpath->exp_time - msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) - && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) + && !memcmp(sdata->dev->dev_addr, hdr->addr4, + ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) && !(mpath->flags & MESH_PATH_FIXED)) { mesh_queue_preq(mpath, @@ -815,7 +811,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) skb_queue_tail(&mpath->frame_queue, skb); if (skb_to_free) - mesh_path_discard_frame(skb_to_free, dev); + mesh_path_discard_frame(skb_to_free, sdata); err = -ENOENT; } @@ -835,7 +831,7 @@ void mesh_path_timer(unsigned long data) if (!mpath) goto endmpathtimer; spin_lock_bh(&mpath->state_lock); - sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); + sdata = mpath->sdata; if (mpath->flags & MESH_PATH_RESOLVED || (!(mpath->flags & MESH_PATH_RESOLVING))) mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 838ee60492ad..0a60f55f32ab 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -62,13 +61,13 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) /** * mesh_path_lookup - look up a path in the mesh path table * @dst: hardware address (ETH_ALEN length) of destination - * @dev: local interface + * @sdata: local subif * * Returns: pointer to the mesh path structure, or NULL if not found * * Locking: must be called within a read rcu section. */ -struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) +struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct hlist_node *n; @@ -78,10 +77,10 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) tbl = rcu_dereference(mesh_paths); - bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)]; + bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; hlist_for_each_entry_rcu(node, n, bucket, list) { mpath = node->mpath; - if (mpath->dev == dev && + if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) { if (MPATH_EXPIRED(mpath)) { spin_lock_bh(&mpath->state_lock); @@ -98,13 +97,13 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index * @idx: index - * @dev: local interface, or NULL for all entries + * @sdata: local subif, or NULL for all entries * * Returns: pointer to the mesh path structure, or NULL if not found. * * Locking: must be called within a read rcu section. */ -struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) +struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) { struct mpath_node *node; struct hlist_node *p; @@ -112,7 +111,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) int j = 0; for_each_mesh_entry(mesh_paths, p, node, i) { - if (dev && node->mpath->dev != dev) + if (sdata && node->mpath->sdata != sdata) continue; if (j++ == idx) { if (MPATH_EXPIRED(node->mpath)) { @@ -131,15 +130,14 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) /** * mesh_path_add - allocate and add a new path to the mesh path table * @addr: destination address of the path (ETH_ALEN length) - * @dev: local interface + * @sdata: local subif * * Returns: 0 on sucess * * State: the initial state of the new path is set to 0 */ -int mesh_path_add(u8 *dst, struct net_device *dev) +int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_path *mpath, *new_mpath; struct mpath_node *node, *new_node; struct hlist_head *bucket; @@ -148,7 +146,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) int err = 0; u32 hash_idx; - if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) /* never add ourselves as neighbours */ return -ENOTSUPP; @@ -169,7 +167,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) read_lock(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); - new_mpath->dev = dev; + new_mpath->sdata = sdata; new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); new_node->mpath = new_mpath; @@ -179,7 +177,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) spin_lock_init(&new_mpath->state_lock); init_timer(&new_mpath->timer); - hash_idx = mesh_table_hash(dst, dev, mesh_paths); + hash_idx = mesh_table_hash(dst, sdata, mesh_paths); bucket = &mesh_paths->hash_buckets[hash_idx]; spin_lock(&mesh_paths->hashwlock[hash_idx]); @@ -187,7 +185,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) err = -EEXIST; hlist_for_each_entry(node, n, bucket, list) { mpath = node->mpath; - if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) == 0) + if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) goto err_exists; } @@ -241,7 +239,7 @@ void mesh_plink_broken(struct sta_info *sta) struct mesh_path *mpath; struct mpath_node *node; struct hlist_node *p; - struct net_device *dev = sta->sdata->dev; + struct ieee80211_sub_if_data *sdata = sta->sdata; int i; rcu_read_lock(); @@ -256,7 +254,7 @@ void mesh_plink_broken(struct sta_info *sta) spin_unlock_bh(&mpath->state_lock); mesh_path_error_tx(mpath->dst, cpu_to_le32(mpath->dsn), - dev->broadcast, dev); + sdata->dev->broadcast, sdata); } else spin_unlock_bh(&mpath->state_lock); } @@ -284,11 +282,11 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) for_each_mesh_entry(mesh_paths, p, node, i) { mpath = node->mpath; if (mpath->next_hop == sta) - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->sdata); } } -void mesh_path_flush(struct net_device *dev) +void mesh_path_flush(struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct mpath_node *node; @@ -297,16 +295,15 @@ void mesh_path_flush(struct net_device *dev) for_each_mesh_entry(mesh_paths, p, node, i) { mpath = node->mpath; - if (mpath->dev == dev) - mesh_path_del(mpath->dst, mpath->dev); + if (mpath->sdata == sdata) + mesh_path_del(mpath->dst, mpath->sdata); } } static void mesh_path_node_reclaim(struct rcu_head *rp) { struct mpath_node *node = container_of(rp, struct mpath_node, rcu); - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(node->mpath->dev); + struct ieee80211_sub_if_data *sdata = node->mpath->sdata; del_timer_sync(&node->mpath->timer); atomic_dec(&sdata->u.sta.mpaths); @@ -318,11 +315,11 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) * mesh_path_del - delete a mesh path from the table * * @addr: dst address (ETH_ALEN length) - * @dev: local interface + * @sdata: local subif * * Returns: 0 if succesful */ -int mesh_path_del(u8 *addr, struct net_device *dev) +int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct mpath_node *node; @@ -332,13 +329,13 @@ int mesh_path_del(u8 *addr, struct net_device *dev) int err = 0; read_lock(&pathtbl_resize_lock); - hash_idx = mesh_table_hash(addr, dev, mesh_paths); + hash_idx = mesh_table_hash(addr, sdata, mesh_paths); bucket = &mesh_paths->hash_buckets[hash_idx]; spin_lock(&mesh_paths->hashwlock[hash_idx]); hlist_for_each_entry(node, n, bucket, list) { mpath = node->mpath; - if (mpath->dev == dev && + if (mpath->sdata == sdata && memcmp(addr, mpath->dst, ETH_ALEN) == 0) { spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; @@ -378,29 +375,29 @@ void mesh_path_tx_pending(struct mesh_path *mpath) * mesh_path_discard_frame - discard a frame whose path could not be resolved * * @skb: frame to discard - * @dev: network device the frame was to be sent through + * @sdata: network subif the frame was to be sent through * * If the frame was beign forwarded from another MP, a PERR frame will be sent * to the precursor. * * Locking: the function must me called within a rcu_read_lock region */ -void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) +void mesh_path_discard_frame(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct mesh_path *mpath; u32 dsn = 0; - if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { + if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { u8 *ra, *da; da = hdr->addr3; ra = hdr->addr2; - mpath = mesh_path_lookup(da, dev); + mpath = mesh_path_lookup(da, sdata); if (mpath) dsn = ++mpath->dsn; - mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev); + mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, sdata); } kfree_skb(skb); @@ -416,14 +413,11 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) */ void mesh_path_flush_pending(struct mesh_path *mpath) { - struct ieee80211_sub_if_data *sdata; struct sk_buff *skb; - sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); - while ((skb = skb_dequeue(&mpath->frame_queue)) && (mpath->flags & MESH_PATH_ACTIVE)) - mesh_path_discard_frame(skb, mpath->dev); + mesh_path_discard_frame(skb, mpath->sdata); } /** @@ -472,7 +466,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) node = hlist_entry(p, struct mpath_node, list); mpath = node->mpath; new_node->mpath = mpath; - hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); + hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl); hlist_add_head(&new_node->list, &newtbl->hash_buckets[hash_idx]); return 0; @@ -489,7 +483,7 @@ int mesh_pathtbl_init(void) return 0; } -void mesh_path_expire(struct net_device *dev) +void mesh_path_expire(struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; struct mpath_node *node; @@ -498,7 +492,7 @@ void mesh_path_expire(struct net_device *dev) read_lock(&pathtbl_resize_lock); for_each_mesh_entry(mesh_paths, p, node, i) { - if (node->mpath->dev != dev) + if (node->mpath->sdata != sdata) continue; mpath = node->mpath; spin_lock_bh(&mpath->state_lock); @@ -507,7 +501,7 @@ void mesh_path_expire(struct net_device *dev) time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) { spin_unlock_bh(&mpath->state_lock); - mesh_path_del(mpath->dst, mpath->dev); + mesh_path_del(mpath->dst, mpath->sdata); } else spin_unlock_bh(&mpath->state_lock); } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 4a7e6d094ff9..7714b0e6e4d7 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -144,10 +144,10 @@ void mesh_plink_deactivate(struct sta_info *sta) spin_unlock_bh(&sta->lock); } -static int mesh_plink_frame_tx(struct net_device *dev, +static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, __le16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; bool include_plid = false; @@ -166,7 +166,7 @@ static int mesh_plink_frame_tx(struct net_device *dev, mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = PLINK_CATEGORY; mgmt->u.action.u.plink_action.action_code = action; @@ -180,7 +180,7 @@ static int mesh_plink_frame_tx(struct net_device *dev, /* two-byte status code followed by two-byte AID */ memset(pos, 0, 4); } - mesh_mgmt_ies_add(skb, dev); + mesh_mgmt_ies_add(skb, sdata); } /* Add Peer Link Management element */ @@ -217,15 +217,14 @@ static int mesh_plink_frame_tx(struct net_device *dev, memcpy(pos, &reason, 2); } - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return 0; } -void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, +void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, bool peer_accepting_plinks) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; rcu_read_lock(); @@ -257,7 +256,6 @@ static void mesh_plink_timer(unsigned long data) { struct sta_info *sta; __le16 llid, plid, reason; - struct net_device *dev = NULL; struct ieee80211_sub_if_data *sdata; #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG DECLARE_MAC_BUF(mac); @@ -282,7 +280,6 @@ static void mesh_plink_timer(unsigned long data) llid = sta->llid; plid = sta->plid; sdata = sta->sdata; - dev = sdata->dev; switch (sta->plink_state) { case PLINK_OPN_RCVD: @@ -299,7 +296,7 @@ static void mesh_plink_timer(unsigned long data) ++sta->plink_retries; mod_plink_timer(sta, sta->plink_timeout); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, 0, 0); break; } @@ -312,7 +309,7 @@ static void mesh_plink_timer(unsigned long data) sta->plink_state = PLINK_HOLDING; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case PLINK_HOLDING: @@ -357,7 +354,7 @@ int mesh_plink_open(struct sta_info *sta) mpl_dbg("Mesh plink: starting establishment with %s\n", print_mac(mac, sta->addr)); - return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN, + return mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, 0, 0); } @@ -403,15 +400,14 @@ int mesh_plink_close(struct sta_info *sta) llid = sta->llid; plid = sta->plid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); return 0; } -void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, +void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee802_11_elems elems; struct sta_info *sta; @@ -478,7 +474,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, /* Now we will figure out the appropriate event... */ event = PLINK_UNDEFINED; - if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) { + if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { switch (ftype) { case PLINK_OPEN: event = OPN_RJCT; @@ -577,9 +573,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, sta->llid = llid; mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, 0, 0); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; default: @@ -604,7 +600,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: @@ -613,7 +609,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, sta->plid = plid; llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; case CNF_ACPT: @@ -646,13 +642,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; case CNF_ACPT: @@ -685,7 +681,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: @@ -695,7 +691,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, spin_unlock_bh(&sta->lock); mpl_dbg("Mesh plink with %s ESTABLISHED\n", print_mac(mac, sta->addr)); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; default: @@ -714,13 +710,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, plid, 0); break; default: @@ -743,7 +739,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, llid = sta->llid; reason = sta->reason; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, reason); break; default: diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ac776c9d48fa..fb8e1e742ca6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -73,19 +73,19 @@ #define IEEE80211_MIN_AMPDU_BUF 0x8 #define IEEE80211_MAX_AMPDU_BUF 0x40 -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); static void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_sta_bss *bss); -static int ieee80211_sta_find_ibss(struct net_device *dev, +static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); -static int ieee80211_sta_wep_configured(struct net_device *dev); -static int ieee80211_sta_start_scan(struct net_device *dev, +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata); +static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); -static int ieee80211_sta_config_auth(struct net_device *dev, +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); static void sta_rx_agg_session_timer_expired(unsigned long data); @@ -239,11 +239,10 @@ static int ecw2cw(int ecw) } -static void ieee80211_sta_def_wmm_params(struct net_device *dev, +static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss, int ibss) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; @@ -281,11 +280,10 @@ static void ieee80211_sta_def_wmm_params(struct net_device *dev, } } -static void ieee80211_sta_wmm_params(struct net_device *dev, +static void ieee80211_sta_wmm_params(struct ieee80211_local *local, struct ieee80211_if_sta *ifsta, u8 *wmm_param, size_t wmm_param_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_tx_queue_params params; size_t left; int count; @@ -349,14 +347,14 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " "cWmin=%d cWmax=%d txop=%d\n", - dev->name, queue, aci, acm, params.aifs, params.cw_min, + local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.txop); #endif /* TODO: handle ACM (block TX, fallback to next lowest allowed * AC for now) */ if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", dev->name, queue); + "parameters for queue %d\n", local->mdev->name, queue); } } } @@ -475,7 +473,7 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( return 0; } -static void ieee80211_sta_send_associnfo(struct net_device *dev, +static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { char *buf; @@ -520,17 +518,16 @@ static void ieee80211_sta_send_associnfo(struct net_device *dev, memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = len; - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); kfree(buf); } -static void ieee80211_set_associated(struct net_device *dev, +static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, bool assoc) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local_to_hw(local)->conf; union iwreq_data wrqu; @@ -544,7 +541,7 @@ static void ieee80211_set_associated(struct net_device *dev, if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, conf->channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -568,12 +565,12 @@ static void ieee80211_set_associated(struct net_device *dev, ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_send_associnfo(dev, ifsta); + ieee80211_sta_send_associnfo(sdata, ifsta); } else { - netif_carrier_off(dev); - ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); + netif_carrier_off(sdata->dev); + ieee80211_sta_tear_down_BA_sessions(sdata, ifsta->bssid); ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - changed |= ieee80211_reset_erp_info(dev); + changed |= ieee80211_reset_erp_info(sdata); sdata->bss_conf.assoc_ht = 0; sdata->bss_conf.ht_conf = NULL; @@ -588,27 +585,24 @@ static void ieee80211_set_associated(struct net_device *dev, ieee80211_bss_info_change_notify(sdata, changed); if (assoc) - netif_carrier_on(dev); + netif_carrier_on(sdata->dev); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); } -static void ieee80211_set_disassoc(struct net_device *dev, +static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int deauth) { if (deauth) ifsta->auth_tries = 0; ifsta->assoc_tries = 0; - ieee80211_set_associated(dev, ifsta, 0); + ieee80211_set_associated(sdata, ifsta, 0); } -void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt) { - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); skb->dev = sdata->local->mdev; skb_set_mac_header(skb, 0); skb_set_network_header(skb, 0); @@ -621,12 +615,12 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, } -static void ieee80211_send_auth(struct net_device *dev, +static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int transaction, u8 *extra, size_t extra_len, int encrypt) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -634,7 +628,7 @@ static void ieee80211_send_auth(struct net_device *dev, sizeof(*mgmt) + 6 + extra_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -646,7 +640,7 @@ static void ieee80211_send_auth(struct net_device *dev, if (encrypt) mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); @@ -655,11 +649,11 @@ static void ieee80211_send_auth(struct net_device *dev, if (extra) memcpy(skb_put(skb, extra_len), extra, extra_len); - ieee80211_sta_tx(dev, skb, encrypt); + ieee80211_sta_tx(sdata, skb, encrypt); } -static void ieee80211_authenticate(struct net_device *dev, +static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { DECLARE_MAC_BUF(mac); @@ -668,16 +662,16 @@ static void ieee80211_authenticate(struct net_device *dev, if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: authentication with AP %s" " timed out\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); ifsta->state = IEEE80211_DISABLED; return; } ifsta->state = IEEE80211_AUTHENTICATE; printk(KERN_DEBUG "%s: authenticate with AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); - ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); + ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } @@ -703,10 +697,10 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, return count; } -static void ieee80211_send_assoc(struct net_device *dev, +static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, *ies; @@ -722,7 +716,7 @@ static void ieee80211_send_assoc(struct net_device *dev, ifsta->ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -738,7 +732,7 @@ static void ieee80211_send_assoc(struct net_device *dev, capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -766,7 +760,7 @@ static void ieee80211_send_assoc(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { @@ -907,21 +901,21 @@ static void ieee80211_send_assoc(struct net_device *dev, if (ifsta->assocreq_ies) memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_deauth(struct net_device *dev, +static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -929,28 +923,28 @@ static void ieee80211_send_deauth(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); skb_put(skb, 2); mgmt->u.deauth.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_disassoc(struct net_device *dev, +static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -958,21 +952,21 @@ static void ieee80211_send_disassoc(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DISASSOC); skb_put(skb, 2); mgmt->u.disassoc.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static int ieee80211_privacy_mismatch(struct net_device *dev, +static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; int bss_privacy; int wep_privacy; @@ -981,14 +975,14 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) return 0; bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); - wep_privacy = !!ieee80211_sta_wep_configured(dev); + wep_privacy = !!ieee80211_sta_wep_configured(sdata); privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); ieee80211_rx_bss_put(local, bss); @@ -1000,7 +994,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, } -static void ieee80211_associate(struct net_device *dev, +static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { DECLARE_MAC_BUF(mac); @@ -1009,31 +1003,31 @@ static void ieee80211_associate(struct net_device *dev, if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { printk(KERN_DEBUG "%s: association with AP %s" " timed out\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); ifsta->state = IEEE80211_DISABLED; return; } ifsta->state = IEEE80211_ASSOCIATE; printk(KERN_DEBUG "%s: associate with AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); - if (ieee80211_privacy_mismatch(dev, ifsta)) { + sdata->dev->name, print_mac(mac, ifsta->bssid)); + if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: mismatch in privacy configuration and " - "mixed-cell disabled - abort association\n", dev->name); + "mixed-cell disabled - abort association\n", sdata->dev->name); ifsta->state = IEEE80211_DISABLED; return; } - ieee80211_send_assoc(dev, ifsta); + ieee80211_send_assoc(sdata, ifsta); mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); } -static void ieee80211_associated(struct net_device *dev, +static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; int disassoc; DECLARE_MAC_BUF(mac); @@ -1050,7 +1044,7 @@ static void ieee80211_associated(struct net_device *dev, sta = sta_info_get(local, ifsta->bssid); if (!sta) { printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; } else { disassoc = 0; @@ -1060,11 +1054,11 @@ static void ieee80211_associated(struct net_device *dev, printk(KERN_DEBUG "%s: No ProbeResp from " "current AP %s - assume out of " "range\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; sta_info_unlink(&sta); } else - ieee80211_send_probe_req(dev, ifsta->bssid, + ieee80211_send_probe_req(sdata, ifsta->bssid, local->scan_ssid, local->scan_ssid_len); ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; @@ -1073,7 +1067,7 @@ static void ieee80211_associated(struct net_device *dev, if (time_after(jiffies, ifsta->last_probe + IEEE80211_PROBE_INTERVAL)) { ifsta->last_probe = jiffies; - ieee80211_send_probe_req(dev, ifsta->bssid, + ieee80211_send_probe_req(sdata, ifsta->bssid, ifsta->ssid, ifsta->ssid_len); } @@ -1087,7 +1081,7 @@ static void ieee80211_associated(struct net_device *dev, if (disassoc) { ifsta->state = IEEE80211_DISABLED; - ieee80211_set_associated(dev, ifsta, 0); + ieee80211_set_associated(sdata, ifsta, 0); } else { mod_timer(&ifsta->timer, jiffies + IEEE80211_MONITORING_INTERVAL); @@ -1095,10 +1089,10 @@ static void ieee80211_associated(struct net_device *dev, } -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1108,7 +1102,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", dev->name); + "request\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -1117,7 +1111,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, memset(mgmt, 0, 24); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (dst) { memcpy(mgmt->da, dst, ETH_ALEN); memcpy(mgmt->bssid, dst, ETH_ALEN); @@ -1152,13 +1146,12 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, *pos = rate->bitrate / 5; } - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static int ieee80211_sta_wep_configured(struct net_device *dev) +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata || !sdata->default_key || sdata->default_key->conf.alg != ALG_WEP) return 0; @@ -1166,16 +1159,16 @@ static int ieee80211_sta_wep_configured(struct net_device *dev) } -static void ieee80211_auth_completed(struct net_device *dev, +static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - printk(KERN_DEBUG "%s: authenticated\n", dev->name); + printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); ifsta->flags |= IEEE80211_STA_AUTHENTICATED; - ieee80211_associate(dev, ifsta); + ieee80211_associate(sdata, ifsta); } -static void ieee80211_auth_challenge(struct net_device *dev, +static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1187,17 +1180,16 @@ static void ieee80211_auth_challenge(struct net_device *dev, ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.challenge) return; - ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2, + ieee80211_send_auth(sdata, ifsta, 3, elems.challenge - 2, elems.challenge_len + 2, 1); } -static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, +static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u8 dialog_token, u16 status, u16 policy, u16 buf_size, u16 timeout) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u16 capab; @@ -1206,7 +1198,7 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer " - "for addba resp frame\n", dev->name); + "for addba resp frame\n", sdata->dev->name); return; } @@ -1214,9 +1206,9 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | @@ -1235,17 +1227,16 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return; } -void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, +void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u8 dialog_token, u16 start_seq_num, u16 agg_size, u16 timeout) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1255,16 +1246,16 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for addba request frame\n", dev->name); + "for addba request frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); @@ -1287,14 +1278,13 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(start_seq_num << 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_sta_process_addba_request(struct net_device *dev, +static void ieee80211_sta_process_addba_request(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; struct ieee80211_conf *conf = &hw->conf; struct sta_info *sta; @@ -1426,16 +1416,15 @@ end: spin_unlock_bh(&sta->lock); end_no_lock: - ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, + ieee80211_send_addba_resp(sta->sdata, sta->addr, tid, dialog_token, status, 1, buf_size, timeout); rcu_read_unlock(); } -static void ieee80211_sta_process_addba_resp(struct net_device *dev, +static void ieee80211_sta_process_addba_resp(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; u16 capab; @@ -1497,11 +1486,10 @@ addba_resp_exit: rcu_read_unlock(); } -void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, +void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1511,7 +1499,7 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for delba frame\n", dev->name); + "for delba frame\n", sdata->dev->name); return; } @@ -1519,9 +1507,9 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | @@ -1537,12 +1525,12 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, mgmt->u.action.u.delba.params = cpu_to_le16(params); mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_bar *bar; u16 bar_control = 0; @@ -1550,7 +1538,7 @@ void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "bar frame\n", dev->name); + "bar frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -1559,20 +1547,20 @@ void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); memcpy(bar->ra, ra, ETH_ALEN); - memcpy(bar->ta, dev->dev_addr, ETH_ALEN); + memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; bar_control |= (u16)(tid << 12); bar->control = cpu_to_le16(bar_control); bar->start_seq_num = cpu_to_le16(ssn); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 initiator, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; int ret, i; @@ -1620,7 +1608,7 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, /* check if this is a self generated aggregation halt */ if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) - ieee80211_send_delba(dev, ra, tid, 0, reason); + ieee80211_send_delba(sdata, ra, tid, 0, reason); /* free the reordering buffer */ for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { @@ -1641,10 +1629,10 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, } -static void ieee80211_sta_process_delba(struct net_device *dev, +static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; u16 tid, params; u16 initiator; @@ -1671,7 +1659,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, #endif /* CONFIG_MAC80211_HT_DEBUG */ if (initiator == WLAN_BACK_INITIATOR) - ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, + ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid, WLAN_BACK_INITIATOR, 0); else { /* WLAN_BACK_RECIPIENT */ spin_lock_bh(&sta->lock); @@ -1758,31 +1746,31 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); #endif - ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, (u16)*ptid, WLAN_BACK_TIMER, WLAN_REASON_QSTA_TIMEOUT); } -void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int i; for (i = 0; i < STA_TID_NUM; i++) { ieee80211_stop_tx_ba_session(&local->hw, addr, i, WLAN_BACK_INITIATOR); - ieee80211_sta_stop_rx_ba_session(dev, addr, i, + ieee80211_sta_stop_rx_ba_session(sdata, addr, i, WLAN_BACK_RECIPIENT, WLAN_REASON_QSTA_LEAVE_QBSS); } } -static void ieee80211_send_refuse_measurement_request(struct net_device *dev, +static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, struct ieee80211_msrment_ie *request_ie, const u8 *da, const u8 *bssid, u8 dialog_token) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *msr_report; @@ -1791,7 +1779,7 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", dev->name); + "measurement report frame\n", sdata->dev->name); return; } @@ -1799,7 +1787,7 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); memset(msr_report, 0, 24); memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); + memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(msr_report->bssid, bssid, ETH_ALEN); msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); @@ -1821,10 +1809,10 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_sta_process_measurement_req(struct net_device *dev, +static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -1835,19 +1823,18 @@ static void ieee80211_sta_process_measurement_req(struct net_device *dev, * For now just refuse * TODO: Answer basic measurement as unmeasured */ - ieee80211_send_refuse_measurement_request(dev, + ieee80211_send_refuse_measurement_request(sdata, &mgmt->u.action.u.measurement.msr_elem, mgmt->sa, mgmt->bssid, mgmt->u.action.u.measurement.dialog_token); } -static void ieee80211_rx_mgmt_auth(struct net_device *dev, +static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); u16 auth_alg, auth_transaction, status_code; DECLARE_MAC_BUF(mac); @@ -1879,7 +1866,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, */ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) return; - ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); + ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); } if (auth_alg != ifsta->auth_alg || @@ -1912,7 +1899,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, algs[pos] == 0xff) continue; if (algs[pos] == WLAN_AUTH_SHARED_KEY && - !ieee80211_sta_wep_configured(dev)) + !ieee80211_sta_wep_configured(sdata)) continue; ifsta->auth_alg = algs[pos]; break; @@ -1924,19 +1911,19 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, switch (ifsta->auth_alg) { case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: - ieee80211_auth_completed(dev, ifsta); + ieee80211_auth_completed(sdata, ifsta); break; case WLAN_AUTH_SHARED_KEY: if (ifsta->auth_transaction == 4) - ieee80211_auth_completed(dev, ifsta); + ieee80211_auth_completed(sdata, ifsta); else - ieee80211_auth_challenge(dev, ifsta, mgmt, len); + ieee80211_auth_challenge(sdata, ifsta, mgmt, len); break; } } -static void ieee80211_rx_mgmt_deauth(struct net_device *dev, +static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1953,7 +1940,7 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) - printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); + printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); if (ifsta->state == IEEE80211_AUTHENTICATE || ifsta->state == IEEE80211_ASSOCIATE || @@ -1963,12 +1950,12 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(dev, ifsta, 1); + ieee80211_set_disassoc(sdata, ifsta, 1); ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; } -static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, +static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1985,7 +1972,7 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); if (ifsta->flags & IEEE80211_STA_ASSOCIATED) - printk(KERN_DEBUG "%s: disassociated\n", dev->name); + printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); if (ifsta->state == IEEE80211_ASSOCIATED) { ifsta->state = IEEE80211_ASSOCIATE; @@ -1993,7 +1980,7 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_set_disassoc(sdata, ifsta, 0); } @@ -2004,7 +1991,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, int reassoc) { struct ieee80211_local *local = sdata->local; - struct net_device *dev = sdata->dev; struct ieee80211_supported_band *sband; struct sta_info *sta; u64 rates, basic_rates; @@ -2034,12 +2020,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " "status=%d aid=%d)\n", - dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), + sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - dev->name, status_code); + sdata->dev->name, status_code); /* if this was a reassociation, ensure we try a "full" * association next time. This works around some broken APs * which do not correctly reject reassociation requests. */ @@ -2049,7 +2035,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", dev->name, aid); + "set\n", sdata->dev->name, aid); aid &= ~(BIT(15) | BIT(14)); pos = mgmt->u.assoc_resp.variable; @@ -2057,11 +2043,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", - dev->name); + sdata->dev->name); return; } - printk(KERN_DEBUG "%s: associated\n", dev->name); + printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); ifsta->aid = aid; ifsta->ap_capab = capab_info; @@ -2082,11 +2068,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" - " the AP\n", dev->name); + " the AP\n", sdata->dev->name); rcu_read_unlock(); return; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -2099,7 +2085,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, err = sta_info_insert(sta); if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", dev->name, err); + " the AP (error %d)\n", sdata->dev->name, err); rcu_read_unlock(); return; } @@ -2179,7 +2165,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (elems.wmm_param) { set_sta_flags(sta, WLAN_STA_WME); rcu_read_unlock(); - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); } else rcu_read_unlock(); @@ -2188,17 +2174,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * ieee80211_set_associated() will tell the driver */ bss_conf->aid = aid; bss_conf->assoc_capability = capab_info; - ieee80211_set_associated(dev, ifsta, 1); + ieee80211_set_associated(sdata, ifsta, 1); - ieee80211_associated(dev, ifsta); + ieee80211_associated(sdata, ifsta); } /* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_add(struct net_device *dev, +static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, struct ieee80211_sta_bss *bss) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); u8 hash_idx; if (bss_mesh_cfg(bss)) @@ -2234,10 +2219,10 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); @@ -2255,16 +2240,15 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); + __ieee80211_rx_bss_hash_add(local, bss); spin_unlock_bh(&local->sta_bss_lock); return bss; } static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); @@ -2286,10 +2270,9 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, #ifdef CONFIG_MAC80211_MESH static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, +ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int freq) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); @@ -2311,10 +2294,9 @@ ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, } static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, +ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int mesh_config_len, int freq) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; if (mesh_config_len != MESH_CFG_LEN) @@ -2348,7 +2330,7 @@ ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); + __ieee80211_rx_bss_hash_add(local, bss); spin_unlock_bh(&local->sta_bss_lock); return bss; } @@ -2399,23 +2381,20 @@ void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) } -static int ieee80211_sta_join_ibss(struct net_device *dev, +static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_sta_bss *bss) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int res, rates, i, j; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; - struct ieee80211_sub_if_data *sdata; struct ieee80211_supported_band *sband; union iwreq_data wrqu; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* Remove possible STA entries from other IBSS networks. */ sta_info_flush_delayed(sdata); @@ -2433,7 +2412,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, sdata->drop_unencrypted = bss->capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - res = ieee80211_set_freq(dev, bss->freq); + res = ieee80211_set_freq(sdata, bss->freq); if (res) return res; @@ -2449,7 +2428,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int); @@ -2506,14 +2485,14 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, } ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; - ieee80211_sta_def_wmm_params(dev, bss, 1); + ieee80211_sta_def_wmm_params(sdata, bss, 1); ifsta->state = IEEE80211_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); return res; } @@ -2555,35 +2534,34 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, } -static void ieee80211_rx_bss_info(struct net_device *dev, +static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status, struct ieee802_11_elems *elems, int beacon) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int freq, clen; struct ieee80211_sta_bss *bss; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); u64 beacon_timestamp, rx_timestamp; struct ieee80211_channel *channel; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); - if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN)) + if (!beacon && memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) return; /* ignore ProbeResp to foreign address */ beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && - elems->mesh_config && mesh_matches_local(elems, dev)) { + elems->mesh_config && mesh_matches_local(elems, sdata)) { u64 rates = ieee80211_sta_get_rates(local, elems, rx_status->band); - mesh_neighbour_update(mgmt->sa, rates, dev, - mesh_peer_accepts_plinks(elems, dev)); + mesh_neighbour_update(mgmt->sa, rates, sdata, + mesh_peer_accepts_plinks(elems)); } rcu_read_lock(); @@ -2620,21 +2598,21 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_get(dev, elems->mesh_id, + bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, elems->mesh_id_len, elems->mesh_config, freq); else #endif - bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, + bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) { #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_add(dev, elems->mesh_id, + bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, elems->mesh_id_len, elems->mesh_config, elems->mesh_config_len, freq); else #endif - bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, + bss = ieee80211_rx_bss_add(sdata, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) return; @@ -2871,10 +2849,10 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #ifndef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: beacon TSF higher than " "local TSF - IBSS merge with BSSID %s\n", - dev->name, print_mac(mac, mgmt->bssid)); + sdata->dev->name, print_mac(mac, mgmt->bssid)); #endif - ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); - ieee80211_ibss_add_sta(dev, NULL, + ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); + ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, mgmt->sa, BIT(rx_status->rate_idx)); } @@ -2884,7 +2862,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, } -static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, +static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) @@ -2899,20 +2877,19 @@ static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 0); } -static void ieee80211_rx_mgmt_beacon(struct net_device *dev, +static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; size_t baselen; struct ieee802_11_elems elems; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local->hw.conf; u32 changed = 0; @@ -2923,9 +2900,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 1); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; ifsta = &sdata->u.sta; @@ -2934,7 +2910,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); /* Do not send changes to driver if we are scanning. This removes @@ -2966,14 +2942,13 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, } -static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, +static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int tx_last_beacon; struct sk_buff *skb; struct ieee80211_mgmt *resp; @@ -2997,7 +2972,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" "%s (tx_last_beacon=%d)\n", - dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), + sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), print_mac(mac3, mgmt->bssid), tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ @@ -3015,7 +2990,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " "from %s\n", - dev->name, print_mac(mac, mgmt->sa)); + sdata->dev->name, print_mac(mac, mgmt->sa)); #endif return; } @@ -3035,19 +3010,18 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, memcpy(resp->da, mgmt->sa, ETH_ALEN); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", - dev->name, print_mac(mac, resp->da)); + sdata->dev->name, print_mac(mac, resp->da)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_rx_mgmt_action(struct net_device *dev, +static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (len < IEEE80211_MIN_ACTION_SIZE) return; @@ -3061,7 +3035,7 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.measurement))) break; - ieee80211_sta_process_measurement_req(dev, mgmt, len); + ieee80211_sta_process_measurement_req(sdata, mgmt, len); break; } break; @@ -3071,38 +3045,37 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_req))) break; - ieee80211_sta_process_addba_request(dev, mgmt, len); + ieee80211_sta_process_addba_request(local, mgmt, len); break; case WLAN_ACTION_ADDBA_RESP: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_resp))) break; - ieee80211_sta_process_addba_resp(dev, mgmt, len); + ieee80211_sta_process_addba_resp(local, mgmt, len); break; case WLAN_ACTION_DELBA: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.delba))) break; - ieee80211_sta_process_delba(dev, mgmt, len); + ieee80211_sta_process_delba(sdata, mgmt, len); break; } break; case PLINK_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_plink_frame(dev, mgmt, len, rx_status); + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); break; case MESH_PATH_SEL_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_path_sel_frame(dev, mgmt, len); + mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; struct ieee80211_mgmt *mgmt; u16 fc; @@ -3110,7 +3083,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, if (skb->len < 24) goto fail; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; mgmt = (struct ieee80211_mgmt *) skb->data; @@ -3137,16 +3109,14 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, } -static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, +static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_rx_status *rx_status; - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; struct ieee80211_mgmt *mgmt; u16 fc; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; rx_status = (struct ieee80211_rx_status *) skb->cb; @@ -3155,17 +3125,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len, + ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_BEACON: - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_AUTH: - ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_ASSOC_RESP: ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); @@ -3174,13 +3144,13 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); break; case IEEE80211_STYPE_DEAUTH: - ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_DISASSOC: - ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: - ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status); break; } @@ -3189,7 +3159,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, ieee80211_rx_result -ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, +ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { struct ieee80211_mgmt *mgmt; @@ -3208,13 +3178,13 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, return RX_DROP_MONITOR; if (ieee80211_is_probe_resp(fc)) { - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); dev_kfree_skb(skb); return RX_QUEUED; } if (ieee80211_is_beacon(fc)) { - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); dev_kfree_skb(skb); return RX_QUEUED; } @@ -3223,12 +3193,11 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, } -static int ieee80211_sta_active_ibss(struct net_device *dev) +static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int active = 0; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -3247,9 +3216,9 @@ static int ieee80211_sta_active_ibss(struct net_device *dev) } -static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) +static void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta, *tmp; LIST_HEAD(tmp_list); DECLARE_MAC_BUF(mac); @@ -3260,7 +3229,7 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %s\n", - dev->name, print_mac(mac, sta->addr)); + sdata->dev->name, print_mac(mac, sta->addr)); #endif __sta_info_unlink(&sta); if (sta) @@ -3273,30 +3242,29 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) } -static void ieee80211_sta_merge_ibss(struct net_device *dev, +static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); - ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT); - if (ieee80211_sta_active_ibss(dev)) + ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); + if (ieee80211_sta_active_ibss(sdata)) return; printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " - "IBSS networks with same SSID (merge)\n", dev->name); - ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len); + "IBSS networks with same SSID (merge)\n", sdata->dev->name); + ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); } #ifdef CONFIG_MAC80211_MESH -static void ieee80211_mesh_housekeeping(struct net_device *dev, +static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); bool free_plinks; - ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); - mesh_path_expire(dev); + ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); + mesh_path_expire(sdata); free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.sta.accepting_plinks) @@ -3307,10 +3275,9 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev, } -void ieee80211_start_mesh(struct net_device *dev) +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_sta *ifsta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; ifsta->state = IEEE80211_MESH_UP; ieee80211_sta_timer((unsigned long)sdata); @@ -3324,7 +3291,7 @@ void ieee80211_sta_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(&sdata->wdev); + struct ieee80211_local *local = sdata->local; set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); queue_work(local->hw.workqueue, &ifsta->work); @@ -3334,12 +3301,11 @@ void ieee80211_sta_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, u.sta.work); - struct net_device *dev = sdata->dev; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; struct sk_buff *skb; - if (!netif_running(dev)) + if (!netif_running(sdata->dev)) return; if (local->sta_sw_scanning || local->sta_hw_scanning) @@ -3352,27 +3318,27 @@ void ieee80211_sta_work(struct work_struct *work) ifsta = &sdata->u.sta; while ((skb = skb_dequeue(&ifsta->skb_queue))) - ieee80211_sta_rx_queued_mgmt(dev, skb); + ieee80211_sta_rx_queued_mgmt(sdata, skb); #ifdef CONFIG_MAC80211_MESH if (ifsta->preq_queue_len && time_after(jiffies, ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) - mesh_path_start_discovery(dev); + mesh_path_start_discovery(sdata); #endif if (ifsta->state != IEEE80211_AUTHENTICATE && ifsta->state != IEEE80211_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { if (ifsta->scan_ssid_len) - ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len); + ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); else - ieee80211_sta_start_scan(dev, NULL, 0); + ieee80211_sta_start_scan(sdata, NULL, 0); return; } if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { - if (ieee80211_sta_config_auth(dev, ifsta)) + if (ieee80211_sta_config_auth(sdata, ifsta)) return; clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) @@ -3382,23 +3348,23 @@ void ieee80211_sta_work(struct work_struct *work) case IEEE80211_DISABLED: break; case IEEE80211_AUTHENTICATE: - ieee80211_authenticate(dev, ifsta); + ieee80211_authenticate(sdata, ifsta); break; case IEEE80211_ASSOCIATE: - ieee80211_associate(dev, ifsta); + ieee80211_associate(sdata, ifsta); break; case IEEE80211_ASSOCIATED: - ieee80211_associated(dev, ifsta); + ieee80211_associated(sdata, ifsta); break; case IEEE80211_IBSS_SEARCH: - ieee80211_sta_find_ibss(dev, ifsta); + ieee80211_sta_find_ibss(sdata, ifsta); break; case IEEE80211_IBSS_JOINED: - ieee80211_sta_merge_ibss(dev, ifsta); + ieee80211_sta_merge_ibss(sdata, ifsta); break; #ifdef CONFIG_MAC80211_MESH case IEEE80211_MESH_UP: - ieee80211_mesh_housekeeping(dev, ifsta); + ieee80211_mesh_housekeeping(sdata, ifsta); break; #endif default: @@ -3406,20 +3372,20 @@ void ieee80211_sta_work(struct work_struct *work) break; } - if (ieee80211_privacy_mismatch(dev, ifsta)) { + if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: privacy configuration mismatch and " - "mixed-cell disabled - disassociate\n", dev->name); + "mixed-cell disabled - disassociate\n", sdata->dev->name); - ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED); - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_send_disassoc(sdata, ifsta, WLAN_REASON_UNSPECIFIED); + ieee80211_set_disassoc(sdata, ifsta, 0); } } -static void ieee80211_sta_reset_auth(struct net_device *dev, +static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (local->ops->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ @@ -3440,15 +3406,14 @@ static void ieee80211_sta_reset_auth(struct net_device *dev, ifsta->auth_transaction = -1; ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; ifsta->auth_tries = ifsta->assoc_tries = 0; - netif_carrier_off(dev); + netif_carrier_off(sdata->dev); } -void ieee80211_sta_req_auth(struct net_device *dev, +void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; @@ -3492,11 +3457,10 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, return 0; } -static int ieee80211_sta_config_auth(struct net_device *dev, +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss, *selected = NULL; int top_rssi = 0, freq; @@ -3535,22 +3499,22 @@ static int ieee80211_sta_config_auth(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); if (selected) { - ieee80211_set_freq(dev, selected->freq); + ieee80211_set_freq(sdata, selected->freq); if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) - ieee80211_sta_set_ssid(dev, selected->ssid, + ieee80211_sta_set_ssid(sdata, selected->ssid, selected->ssid_len); - ieee80211_sta_set_bssid(dev, selected->bssid); - ieee80211_sta_def_wmm_params(dev, selected, 0); + ieee80211_sta_set_bssid(sdata, selected->bssid); + ieee80211_sta_def_wmm_params(sdata, selected, 0); ieee80211_rx_bss_put(local, selected); ifsta->state = IEEE80211_AUTHENTICATE; - ieee80211_sta_reset_auth(dev, ifsta); + ieee80211_sta_reset_auth(sdata, ifsta); return 0; } else { if (ifsta->state != IEEE80211_AUTHENTICATE) { if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(dev, NULL, 0); + ieee80211_sta_start_scan(sdata, NULL, 0); else - ieee80211_sta_start_scan(dev, ifsta->ssid, + ieee80211_sta_start_scan(sdata, ifsta->ssid, ifsta->ssid_len); ifsta->state = IEEE80211_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); @@ -3561,12 +3525,11 @@ static int ieee80211_sta_config_auth(struct net_device *dev, } -static int ieee80211_sta_create_ibss(struct net_device *dev, +static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN], *pos; int i; @@ -3582,15 +3545,15 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, * random number generator get different BSSID. */ get_random_bytes(bssid, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= dev->dev_addr[i]; + bssid[i] ^= sdata->dev->dev_addr[i]; bssid[0] &= ~0x01; bssid[0] |= 0x02; #endif printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", - dev->name, print_mac(mac, bssid)); + sdata->dev->name, print_mac(mac, bssid)); - bss = ieee80211_rx_bss_add(dev, bssid, + bss = ieee80211_rx_bss_add(sdata, bssid, local->hw.conf.channel->center_freq, sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) @@ -3617,16 +3580,16 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, *pos++ = (u8) (rate / 5); } - ret = ieee80211_sta_join_ibss(dev, ifsta, bss); + ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); ieee80211_rx_bss_put(local, bss); return ret; } -static int ieee80211_sta_find_ibss(struct net_device *dev, +static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; int found = 0; u8 bssid[ETH_ALEN]; @@ -3637,10 +3600,10 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, if (ifsta->ssid_len == 0) return -EINVAL; - active_ibss = ieee80211_sta_active_ibss(dev); + active_ibss = ieee80211_sta_active_ibss(sdata); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", - dev->name, active_ibss); + sdata->dev->name, active_ibss); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ spin_lock_bh(&local->sta_bss_lock); list_for_each_entry(bss, &local->sta_bss_list, list) { @@ -3675,15 +3638,15 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, else search_freq = local->hw.conf.channel->center_freq; - bss = ieee80211_rx_bss_get(dev, bssid, search_freq, + bss = ieee80211_rx_bss_get(local, bssid, search_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) goto dont_join; printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", - dev->name, print_mac(mac, bssid)); - ret = ieee80211_sta_join_ibss(dev, ifsta, bss); + sdata->dev->name, print_mac(mac, bssid)); + ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); ieee80211_rx_bss_put(local, bss); return ret; } @@ -3695,14 +3658,14 @@ dont_join: /* Selected IBSS not found in current scan results - try to scan */ if (ifsta->state == IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(dev)) { + !ieee80211_sta_active_ibss(sdata)) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); } else if (time_after(jiffies, local->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " - "join\n", dev->name); - return ieee80211_sta_req_scan(dev, ifsta->ssid, + "join\n", sdata->dev->name); + return ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); } else if (ifsta->state != IEEE80211_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; @@ -3712,10 +3675,10 @@ dont_join: if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS))) - return ieee80211_sta_create_ibss(dev, ifsta); + return ieee80211_sta_create_ibss(sdata, ifsta); if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { printk(KERN_DEBUG "%s: IBSS not allowed on" - " %d MHz\n", dev->name, + " %d MHz\n", sdata->dev->name, local->hw.conf.channel->center_freq); } @@ -3733,9 +3696,8 @@ dont_join: } -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) +int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta; int res; @@ -3759,7 +3721,7 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); if (res) { printk(KERN_DEBUG "%s: Failed to config new SSID to " - "the low-level driver\n", dev->name); + "the low-level driver\n", sdata->dev->name); return res; } } @@ -3773,16 +3735,15 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { ifsta->ibss_join_req = jiffies; ifsta->state = IEEE80211_IBSS_SEARCH; - return ieee80211_sta_find_ibss(dev, ifsta); + return ieee80211_sta_find_ibss(sdata, ifsta); } return 0; } -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) +int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; memcpy(ssid, ifsta->ssid, ifsta->ssid_len); *len = ifsta->ssid_len; @@ -3790,13 +3751,11 @@ int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) } -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) +int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) { - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; int res; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { @@ -3809,7 +3768,7 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); if (res) { printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", dev->name); + "the low-level driver\n", sdata->dev->name); return res; } } @@ -3850,7 +3809,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_tx(sdata->dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } @@ -3923,8 +3882,8 @@ done: struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || (!(ifsta->state == IEEE80211_IBSS_JOINED) && - !ieee80211_sta_active_ibss(dev))) - ieee80211_sta_find_ibss(dev, ifsta); + !ieee80211_sta_active_ibss(sdata))) + ieee80211_sta_find_ibss(sdata, ifsta); } } EXPORT_SYMBOL(ieee80211_scan_completed); @@ -4013,7 +3972,7 @@ void ieee80211_sta_scan_work(struct work_struct *work) if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) break; - ieee80211_send_probe_req(dev, NULL, local->scan_ssid, + ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, local->scan_ssid_len); next_delay = IEEE80211_CHANNEL_TIME; break; @@ -4025,10 +3984,10 @@ void ieee80211_sta_scan_work(struct work_struct *work) } -static int ieee80211_sta_start_scan(struct net_device *dev, +static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = scan_sdata->local; struct ieee80211_sub_if_data *sdata; if (ssid_len > IEEE80211_MAX_SSID_LEN) @@ -4052,7 +4011,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, */ if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == dev) + if (local->scan_dev == scan_sdata->dev) return 0; return -EBUSY; } @@ -4062,7 +4021,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, ssid, ssid_len); if (!rc) { local->sta_hw_scanning = 1; - local->scan_dev = dev; + local->scan_dev = scan_sdata->dev; } return rc; } @@ -4086,7 +4045,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, local->scan_state = SCAN_SET_CHANNEL; local->scan_channel_idx = 0; local->scan_band = IEEE80211_BAND_2GHZ; - local->scan_dev = dev; + local->scan_dev = scan_sdata->dev; netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; @@ -4105,17 +4064,16 @@ static int ieee80211_sta_start_scan(struct net_device *dev, } -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return ieee80211_sta_start_scan(dev, ssid, ssid_len); + return ieee80211_sta_start_scan(sdata, ssid, ssid_len); if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == dev) + if (local->scan_dev == sdata->dev) return 0; return -EBUSY; } @@ -4129,12 +4087,11 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) } static char * -ieee80211_sta_scan_result(struct net_device *dev, +ieee80211_sta_scan_result(struct ieee80211_local *local, struct iw_request_info *info, struct ieee80211_sta_bss *bss, char *current_ev, char *end_buf) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct iw_event iwe; if (time_after(jiffies, @@ -4321,11 +4278,10 @@ ieee80211_sta_scan_result(struct net_device *dev, } -int ieee80211_sta_scan_results(struct net_device *dev, +int ieee80211_sta_scan_results(struct ieee80211_local *local, struct iw_request_info *info, char *buf, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); char *current_ev = buf; char *end_buf = buf + len; struct ieee80211_sta_bss *bss; @@ -4336,7 +4292,7 @@ int ieee80211_sta_scan_results(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); return -E2BIG; } - current_ev = ieee80211_sta_scan_result(dev, info, bss, + current_ev = ieee80211_sta_scan_result(local, info, bss, current_ev, end_buf); } spin_unlock_bh(&local->sta_bss_lock); @@ -4344,9 +4300,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, } -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; kfree(ifsta->extra_ie); @@ -4366,13 +4321,12 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) } -struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, +struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); DECLARE_MAC_BUF(mac); int band = local->hw.conf.channel->band; @@ -4381,7 +4335,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: No room for a new IBSS STA " - "entry %s\n", dev->name, print_mac(mac, addr)); + "entry %s\n", sdata->dev->name, print_mac(mac, addr)); } return NULL; } @@ -4391,7 +4345,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", - wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); + wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name); #endif sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); @@ -4414,31 +4368,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, } -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason) +int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", - dev->name, reason); + sdata->dev->name, reason); if (sdata->vif.type != IEEE80211_IF_TYPE_STA && sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return -EINVAL; - ieee80211_send_deauth(dev, ifsta, reason); - ieee80211_set_disassoc(dev, ifsta, 1); + ieee80211_send_deauth(sdata, ifsta, reason); + ieee80211_set_disassoc(sdata, ifsta, 1); return 0; } -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) +int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", - dev->name, reason); + sdata->dev->name, reason); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return -EINVAL; @@ -4446,8 +4398,8 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) return -1; - ieee80211_send_disassoc(dev, ifsta, reason); - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_send_disassoc(sdata, ifsta, reason); + ieee80211_set_disassoc(sdata, ifsta, 0); return 0; } @@ -4464,7 +4416,7 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, if (sdata->vif.type != IEEE80211_IF_TYPE_STA) continue; - ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); } rcu_read_unlock(); break; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2464263cb7a5..fd83ef760a37 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -404,11 +404,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) struct sk_buff *skb = rx->skb; if (unlikely(local->sta_hw_scanning)) - return ieee80211_sta_rx_scan(rx->dev, skb, rx->status); + return ieee80211_sta_rx_scan(rx->sdata, skb, rx->status); if (unlikely(local->sta_sw_scanning)) { /* drop all the other packets during a software scan anyway */ - if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status) + if (ieee80211_sta_rx_scan(rx->sdata, skb, rx->status) != RX_QUEUED) dev_kfree_skb(skb); return RX_QUEUED; @@ -466,7 +466,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_data(hdr->frame_control) && is_multicast_ether_addr(hdr->addr1) && - mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) + mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) return RX_DROP_MONITOR; #undef msh_h_get @@ -1523,7 +1523,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) sdata->vif.type == IEEE80211_IF_TYPE_IBSS || sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) && !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) - ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status); + ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); else return RX_DROP_MONITOR; @@ -1570,7 +1570,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, !ieee80211_is_auth(hdr->frame_control)) goto ignore; - mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); + mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); ignore: dev_kfree_skb(rx->skb); rx->skb = NULL; @@ -1744,7 +1744,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; if (ieee80211_is_beacon(hdr->frame_control)) { if (!rx->sta) - rx->sta = ieee80211_ibss_add_sta(sdata->dev, + rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb, bssid, hdr->addr2, BIT(rx->status->rate_idx)); return 1; @@ -1760,7 +1760,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; rx->flags &= ~IEEE80211_RX_RA_MATCH; } else if (!rx->sta) - rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, + rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb, bssid, hdr->addr2, BIT(rx->status->rate_idx)); break; @@ -2066,7 +2066,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, /* if this mpdu is fragmented - terminate rx aggregation session */ sc = le16_to_cpu(hdr->seq_ctrl); if (sc & IEEE80211_SCTL_FRAG) { - ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); ret = 1; goto end_reorder; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 85f3ba85c132..c413d4836afe 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1327,7 +1327,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (is_multicast_ether_addr(hdr->addr3)) memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); else - if (mesh_nexthop_lookup(skb, odev)) + if (mesh_nexthop_lookup(skb, osdata)) return 0; if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, @@ -1908,7 +1908,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, *pos++ = WLAN_EID_SSID; *pos++ = 0x0; - mesh_mgmt_ies_add(skb, sdata->dev); + mesh_mgmt_ies_add(skb, sdata); num_beacons = &sdata->u.sta.num_beacons; } else { diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 34fa8ed1e784..735daa355c37 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -27,22 +27,19 @@ #include "aes_ccm.h" -static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, +static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, int idx, int alg, int remove, int set_tx_key, const u8 *_key, size_t key_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; struct ieee80211_key *key; - struct ieee80211_sub_if_data *sdata; int err; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", - dev->name, idx); + sdata->dev->name, idx); return -EINVAL; } @@ -127,11 +124,11 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length); + int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); if (ret) return ret; sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; - ieee80211_sta_req_auth(dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; } @@ -333,12 +330,11 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, return 0; } -int ieee80211_set_freq(struct net_device *dev, int freqMHz) +int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) { int ret = -EINVAL; struct ieee80211_channel *chan; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); @@ -346,7 +342,7 @@ int ieee80211_set_freq(struct net_device *dev, int freqMHz) if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && chan->flags & IEEE80211_CHAN_NO_IBSS) { printk(KERN_DEBUG "%s: IBSS not allowed on frequency " - "%d MHz\n", dev->name, chan->center_freq); + "%d MHz\n", sdata->dev->name, chan->center_freq); return ret; } local->oper_channel = chan; @@ -379,14 +375,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; } else - return ieee80211_set_freq(dev, + return ieee80211_set_freq(sdata, ieee80211_channel_to_frequency(freq->m)); } else { int i, div = 1000000; for (i = 0; i < freq->e; i++) div /= 10; if (div > 0) - return ieee80211_set_freq(dev, freq->m / div); + return ieee80211_set_freq(sdata, freq->m / div); else return -EINVAL; } @@ -432,10 +428,10 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; else sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL; - ret = ieee80211_sta_set_ssid(dev, ssid, len); + ret = ieee80211_sta_set_ssid(sdata, ssid, len); if (ret) return ret; - ieee80211_sta_req_auth(dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; } @@ -460,7 +456,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - int res = ieee80211_sta_get_ssid(dev, ssid, &len); + int res = ieee80211_sta_get_ssid(sdata, ssid, &len); if (res == 0) { data->length = len; data->flags = 1; @@ -504,10 +500,10 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL; else sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; - ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data); + ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); if (ret) return ret; - ieee80211_sta_req_auth(dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { /* @@ -584,7 +580,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, ssid_len = req->essid_len; } - return ieee80211_sta_req_scan(dev, ssid, ssid_len); + return ieee80211_sta_req_scan(sdata, ssid, ssid_len); } @@ -594,11 +590,14 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, { int res; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (local->sta_sw_scanning || local->sta_hw_scanning) return -EAGAIN; - res = ieee80211_sta_scan_results(dev, info, extra, data->length); + res = ieee80211_sta_scan_results(local, info, extra, data->length); if (res >= 0) { data->length = res; return 0; @@ -894,10 +893,10 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev, switch (mlme->cmd) { case IW_MLME_DEAUTH: /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_deauthenticate(dev, mlme->reason_code); + return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); case IW_MLME_DISASSOC: /* TODO: mlme->addr.sa_data */ - return ieee80211_sta_disassociate(dev, mlme->reason_code); + return ieee80211_sta_disassociate(sdata, mlme->reason_code); default: return -EOPNOTSUPP; } @@ -938,7 +937,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, } return ieee80211_set_encryption( - dev, bcaddr, + sdata, bcaddr, idx, alg, remove, !sdata->default_key, keybuf, erq->length); @@ -1184,7 +1183,7 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, } else idx--; - return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg, + return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, remove, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 2f33df0dcccf..78021780b885 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -127,7 +127,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_UNUSABLE; - mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx, + mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, (void *) skb->data); return RX_DROP_UNUSABLE; } -- cgit v1.2.3 From 8e7cdbb6333ef7654e708bd60e50a123688dcd7b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 3 Aug 2008 14:32:01 +0300 Subject: mac80211: filter probes in ieee80211_rx_mgmt_probe_resp This patch moves filtering statement from ieee80211_rx_bss_info which is called for both beacon and probe to ieee80211_rx_mgmt_probe_resp and save few cycles in beacon parsing. Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fb8e1e742ca6..ae5a5cbabae3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2550,9 +2550,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); - if (!beacon && memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) - return; /* ignore ProbeResp to foreign address */ - beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && @@ -2870,6 +2867,9 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, size_t baselen; struct ieee802_11_elems elems; + if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + return; /* ignore ProbeResp to foreign address */ + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; if (baselen > len) return; -- cgit v1.2.3 From 48c2fc59aa415ba92be0ad3a7e741c46883e3944 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 6 Aug 2008 14:22:01 +0300 Subject: mac80211: cleanup mlme state namespace This patch move add STA_MLME to station mlme state defines. Signed-off-by: Tomas Winkler Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 34 ++++++++++++++-------- net/mac80211/main.c | 2 +- net/mac80211/mlme.c | 72 +++++++++++++++++++++++----------------------- net/mac80211/wext.c | 4 +-- 4 files changed, 61 insertions(+), 51 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b5d3f58a7845..747814f319af 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -292,17 +292,33 @@ struct mesh_config { #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) +/* flags for MLME request*/ +#define IEEE80211_STA_REQ_SCAN 0 +#define IEEE80211_STA_REQ_AUTH 1 +#define IEEE80211_STA_REQ_RUN 2 + +/* flags used for setting mlme state */ +enum ieee80211_sta_mlme_state { + IEEE80211_STA_MLME_DISABLED, + IEEE80211_STA_MLME_AUTHENTICATE, + IEEE80211_STA_MLME_ASSOCIATE, + IEEE80211_STA_MLME_ASSOCIATED, + IEEE80211_STA_MLME_IBSS_SEARCH, + IEEE80211_STA_MLME_IBSS_JOINED, + IEEE80211_STA_MLME_MESH_UP +}; + +/* bitfield of allowed auth algs */ +#define IEEE80211_AUTH_ALG_OPEN BIT(0) +#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) +#define IEEE80211_AUTH_ALG_LEAP BIT(2) + struct ieee80211_if_sta { struct timer_list timer; struct work_struct work; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; - enum { - IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, - IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, - IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, - IEEE80211_MESH_UP - } state; + enum ieee80211_sta_mlme_state state; size_t ssid_len; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; @@ -352,13 +368,7 @@ struct ieee80211_if_sta { unsigned long last_probe; unsigned int flags; -#define IEEE80211_STA_REQ_SCAN 0 -#define IEEE80211_STA_REQ_AUTH 1 -#define IEEE80211_STA_REQ_RUN 2 -#define IEEE80211_AUTH_ALG_OPEN BIT(0) -#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) -#define IEEE80211_AUTH_ALG_LEAP BIT(2) unsigned int auth_algs; /* bitfield of allowed auth algs */ int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ int auth_transaction; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 819639486653..398ca66bdfcb 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -539,7 +539,7 @@ static int ieee80211_stop(struct net_device *dev) /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: - sdata->u.sta.state = IEEE80211_DISABLED; + sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; memset(sdata->u.sta.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.sta.timer); /* diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ae5a5cbabae3..f05519d1c2c6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -663,11 +663,11 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: authentication with AP %s" " timed out\n", sdata->dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; printk(KERN_DEBUG "%s: authenticate with AP %s\n", sdata->dev->name, print_mac(mac, ifsta->bssid)); @@ -1004,17 +1004,17 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: association with AP %s" " timed out\n", sdata->dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ifsta->state = IEEE80211_ASSOCIATE; + ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; printk(KERN_DEBUG "%s: associate with AP %s\n", sdata->dev->name, print_mac(mac, ifsta->bssid)); if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: mismatch in privacy configuration and " "mixed-cell disabled - abort association\n", sdata->dev->name); - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } @@ -1037,7 +1037,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, * for better APs. */ /* TODO: remove expired BSSes */ - ifsta->state = IEEE80211_ASSOCIATED; + ifsta->state = IEEE80211_STA_MLME_ASSOCIATED; rcu_read_lock(); @@ -1080,7 +1080,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, sta_info_destroy(sta); if (disassoc) { - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; ieee80211_set_associated(sdata, ifsta, 0); } else { mod_timer(&ifsta->timer, jiffies + @@ -1838,7 +1838,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, u16 auth_alg, auth_transaction, status_code; DECLARE_MAC_BUF(mac); - if (ifsta->state != IEEE80211_AUTHENTICATE && + if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return; @@ -1942,10 +1942,10 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); - if (ifsta->state == IEEE80211_AUTHENTICATE || - ifsta->state == IEEE80211_ASSOCIATE || - ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_AUTHENTICATE; + if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || + ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || + ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } @@ -1974,8 +1974,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, if (ifsta->flags & IEEE80211_STA_ASSOCIATED) printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); - if (ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_ASSOCIATE; + if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { + ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } @@ -2005,7 +2005,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, /* AssocResp and ReassocResp have identical structure, so process both * of them in this function. */ - if (ifsta->state != IEEE80211_ASSOCIATE) + if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE) return; if (len < 24 + 6) @@ -2487,7 +2487,7 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ieee80211_sta_def_wmm_params(sdata, bss, 1); - ifsta->state = IEEE80211_IBSS_JOINED; + ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); memset(&wrqu, 0, sizeof(wrqu)); @@ -2960,7 +2960,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, #endif if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS || - ifsta->state != IEEE80211_IBSS_JOINED || + ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || len < 24 + 2 || !ifsta->probe_resp) return; @@ -3279,7 +3279,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_sta *ifsta; ifsta = &sdata->u.sta; - ifsta->state = IEEE80211_MESH_UP; + ifsta->state = IEEE80211_STA_MLME_MESH_UP; ieee80211_sta_timer((unsigned long)sdata); ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); } @@ -3327,8 +3327,8 @@ void ieee80211_sta_work(struct work_struct *work) mesh_path_start_discovery(sdata); #endif - if (ifsta->state != IEEE80211_AUTHENTICATE && - ifsta->state != IEEE80211_ASSOCIATE && + if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && + ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { if (ifsta->scan_ssid_len) ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); @@ -3345,25 +3345,25 @@ void ieee80211_sta_work(struct work_struct *work) return; switch (ifsta->state) { - case IEEE80211_DISABLED: + case IEEE80211_STA_MLME_DISABLED: break; - case IEEE80211_AUTHENTICATE: + case IEEE80211_STA_MLME_AUTHENTICATE: ieee80211_authenticate(sdata, ifsta); break; - case IEEE80211_ASSOCIATE: + case IEEE80211_STA_MLME_ASSOCIATE: ieee80211_associate(sdata, ifsta); break; - case IEEE80211_ASSOCIATED: + case IEEE80211_STA_MLME_ASSOCIATED: ieee80211_associated(sdata, ifsta); break; - case IEEE80211_IBSS_SEARCH: + case IEEE80211_STA_MLME_IBSS_SEARCH: ieee80211_sta_find_ibss(sdata, ifsta); break; - case IEEE80211_IBSS_JOINED: + case IEEE80211_STA_MLME_IBSS_JOINED: ieee80211_sta_merge_ibss(sdata, ifsta); break; #ifdef CONFIG_MAC80211_MESH - case IEEE80211_MESH_UP: + case IEEE80211_STA_MLME_MESH_UP: ieee80211_mesh_housekeeping(sdata, ifsta); break; #endif @@ -3506,20 +3506,20 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, ieee80211_sta_set_bssid(sdata, selected->bssid); ieee80211_sta_def_wmm_params(sdata, selected, 0); ieee80211_rx_bss_put(local, selected); - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; ieee80211_sta_reset_auth(sdata, ifsta); return 0; } else { - if (ifsta->state != IEEE80211_AUTHENTICATE) { + if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE) { if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) ieee80211_sta_start_scan(sdata, NULL, 0); else ieee80211_sta_start_scan(sdata, ifsta->ssid, ifsta->ssid_len); - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); } else - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; } return -1; } @@ -3657,7 +3657,7 @@ dont_join: #endif /* CONFIG_MAC80211_IBSS_DEBUG */ /* Selected IBSS not found in current scan results - try to scan */ - if (ifsta->state == IEEE80211_IBSS_JOINED && + if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED && !ieee80211_sta_active_ibss(sdata)) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); @@ -3667,7 +3667,7 @@ dont_join: "join\n", sdata->dev->name); return ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); - } else if (ifsta->state != IEEE80211_IBSS_JOINED) { + } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, ifsta->ibss_join_req + @@ -3687,7 +3687,7 @@ dont_join: interval = IEEE80211_SCAN_INTERVAL_SLOW; } - ifsta->state = IEEE80211_IBSS_SEARCH; + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; mod_timer(&ifsta->timer, jiffies + interval); return 0; } @@ -3734,7 +3734,7 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { ifsta->ibss_join_req = jiffies; - ifsta->state = IEEE80211_IBSS_SEARCH; + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; return ieee80211_sta_find_ibss(sdata, ifsta); } @@ -3881,7 +3881,7 @@ done: if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!(ifsta->state == IEEE80211_IBSS_JOINED) && + (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && !ieee80211_sta_active_ibss(sdata))) ieee80211_sta_find_ibss(sdata, ifsta); } diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 735daa355c37..beae664ab480 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -535,8 +535,8 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == IEEE80211_IF_TYPE_STA || sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - if (sdata->u.sta.state == IEEE80211_ASSOCIATED || - sdata->u.sta.state == IEEE80211_IBSS_JOINED) { + if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED || + sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) { ap_addr->sa_family = ARPHRD_ETHER; memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); return 0; -- cgit v1.2.3 From 6042a3e3ff7943e4ff5cbcb8c223ea87337501ea Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Fri, 8 Aug 2008 01:50:46 +0300 Subject: mac80211: change number of pre-assoc scans This patch fixes noticed problem in noisy environments of 50+ APs that scan fails to find the requested AP on first try, which leads to connection refusal. second scan has empirically proven to fix this problem in almost all cases. Signed-off-by: Ron Rindjunsky Signed-off-by: Esti Kummer Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 4 +++- net/mac80211/mlme.c | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 747814f319af..c6de3156930c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -361,7 +361,9 @@ struct ieee80211_if_sta { struct sk_buff_head skb_queue; - int auth_tries, assoc_tries; + int assoc_scan_tries; /* number of scans done pre-association */ + int auth_tries; /* retries for auth req */ + int assoc_tries; /* retries for assoc req */ unsigned long request; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f05519d1c2c6..e821d1ac5b00 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -34,6 +34,7 @@ #include "led.h" #include "mesh.h" +#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 #define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_MAX_TRIES 3 #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) @@ -596,6 +597,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, { if (deauth) ifsta->auth_tries = 0; + ifsta->assoc_scan_tries = 0; ifsta->assoc_tries = 0; ieee80211_set_associated(sdata, ifsta, 0); } @@ -3405,7 +3407,9 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, ifsta->auth_alg = WLAN_AUTH_OPEN; ifsta->auth_transaction = -1; ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - ifsta->auth_tries = ifsta->assoc_tries = 0; + ifsta->assoc_scan_tries = 0; + ifsta->auth_tries = 0; + ifsta->assoc_tries = 0; netif_carrier_off(sdata->dev); } @@ -3510,7 +3514,8 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, ieee80211_sta_reset_auth(sdata, ifsta); return 0; } else { - if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE) { + if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { + ifsta->assoc_scan_tries++; if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) ieee80211_sta_start_scan(sdata, NULL, 0); else -- cgit v1.2.3 From 9859b81eaeb8d48563b5fbd90215c0ae606455a3 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Sat, 9 Aug 2008 03:02:19 +0300 Subject: mac80211: add direct probe before association This patch adds a direct probe request as first step in the association flow if data we have is not up to date. Motivation of this step is to make sure that the bss information we have is correct, since last scan could have been done a while ago, and beacons do not fully answer this need as there are potential differences between them and probe responses (e.g. WMM parameter element) Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 9 ++++-- net/mac80211/mlme.c | 79 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 15 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c6de3156930c..8361054fb7cf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -100,7 +100,7 @@ struct ieee80211_sta_bss { u64 timestamp; int beacon_int; - bool probe_resp; + unsigned long last_probe_resp; unsigned long last_update; /* during assocation, we save an ERP value from a probe response so @@ -294,12 +294,14 @@ struct mesh_config { #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) /* flags for MLME request*/ #define IEEE80211_STA_REQ_SCAN 0 -#define IEEE80211_STA_REQ_AUTH 1 -#define IEEE80211_STA_REQ_RUN 2 +#define IEEE80211_STA_REQ_DIRECT_PROBE 1 +#define IEEE80211_STA_REQ_AUTH 2 +#define IEEE80211_STA_REQ_RUN 3 /* flags used for setting mlme state */ enum ieee80211_sta_mlme_state { IEEE80211_STA_MLME_DISABLED, + IEEE80211_STA_MLME_DIRECT_PROBE, IEEE80211_STA_MLME_AUTHENTICATE, IEEE80211_STA_MLME_ASSOCIATE, IEEE80211_STA_MLME_ASSOCIATED, @@ -362,6 +364,7 @@ struct ieee80211_if_sta { struct sk_buff_head skb_queue; int assoc_scan_tries; /* number of scans done pre-association */ + int direct_probe_tries; /* retries for direct probes */ int auth_tries; /* retries for auth req */ int assoc_tries; /* retries for assoc req */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e821d1ac5b00..84999791a332 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -595,8 +595,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int deauth) { - if (deauth) + if (deauth) { + ifsta->direct_probe_tries = 0; ifsta->auth_tries = 0; + } ifsta->assoc_scan_tries = 0; ifsta->assoc_tries = 0; ieee80211_set_associated(sdata, ifsta, 0); @@ -654,6 +656,36 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tx(sdata, skb, encrypt); } +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) +{ + DECLARE_MAC_BUF(mac); + + ifsta->direct_probe_tries++; + if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; + return; + } + + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", + sdata->dev->name, print_mac(mac, ifsta->bssid), + ifsta->direct_probe_tries); + + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); + + /* Direct probe is sent to broadcast address as some APs + * will not answer to direct packet in unassociated state. + */ + ieee80211_send_probe_req(sdata, NULL, + ifsta->ssid, ifsta->ssid_len); + + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); +} + static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) @@ -1947,7 +1979,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } @@ -2540,8 +2572,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status, - struct ieee802_11_elems *elems, - int beacon) + struct ieee802_11_elems *elems) { struct ieee80211_local *local = sdata->local; int freq, clen; @@ -2549,6 +2580,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; u64 beacon_timestamp, rx_timestamp; struct ieee80211_channel *channel; + bool beacon = ieee80211_is_beacon(mgmt->frame_control); DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); @@ -2705,15 +2737,14 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bss->signal = rx_status->signal; bss->noise = rx_status->noise; bss->qual = rx_status->qual; - if (!beacon && !bss->probe_resp) - bss->probe_resp = true; - + if (!beacon) + bss->last_probe_resp = jiffies; /* * In STA mode, the remaining parameters should not be overridden * by beacons because they're not necessarily accurate there. */ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - bss->probe_resp && beacon) { + bss->last_probe_resp && beacon) { ieee80211_rx_bss_put(local, bss); return; } @@ -2868,6 +2899,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, { size_t baselen; struct ieee802_11_elems elems; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) return; /* ignore ProbeResp to foreign address */ @@ -2879,7 +2911,15 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 0); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); + + /* direct probe may be part of the association flow */ + if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, + &ifsta->request)) { + printk(KERN_DEBUG "%s direct probe responded\n", + sdata->dev->name); + ieee80211_authenticate(sdata, ifsta); + } } @@ -2902,7 +2942,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 1); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; @@ -3329,7 +3369,8 @@ void ieee80211_sta_work(struct work_struct *work) mesh_path_start_discovery(sdata); #endif - if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && + if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && + ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { if (ifsta->scan_ssid_len) @@ -3349,6 +3390,9 @@ void ieee80211_sta_work(struct work_struct *work) switch (ifsta->state) { case IEEE80211_STA_MLME_DISABLED: break; + case IEEE80211_STA_MLME_DIRECT_PROBE: + ieee80211_direct_probe(sdata, ifsta); + break; case IEEE80211_STA_MLME_AUTHENTICATE: ieee80211_authenticate(sdata, ifsta); break; @@ -3408,6 +3452,7 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, ifsta->auth_transaction = -1; ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; ifsta->assoc_scan_tries = 0; + ifsta->direct_probe_tries = 0; ifsta->auth_tries = 0; ifsta->assoc_tries = 0; netif_carrier_off(sdata->dev); @@ -3509,8 +3554,18 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, selected->ssid_len); ieee80211_sta_set_bssid(sdata, selected->bssid); ieee80211_sta_def_wmm_params(sdata, selected, 0); + + /* Send out direct probe if no probe resp was received or + * the one we have is outdated + */ + if (!selected->last_probe_resp || + time_after(jiffies, selected->last_probe_resp + + IEEE80211_SCAN_RESULT_EXPIRE)) + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + else + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + ieee80211_rx_bss_put(local, selected); - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; ieee80211_sta_reset_auth(sdata, ifsta); return 0; } else { -- cgit v1.2.3 From 7f93ea3e246db512c0c17b79847f57dd3a2891e1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Aug 2008 21:45:26 +0200 Subject: mac80211: fill start-sequence-number for BA session start Otherwise, drivers are required to keep track of the sequence numbers themselves, and they really shouldn't be since we already do it for them. I'll fix the race once we figure out how this code should work at all, it's currently disabled. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 398ca66bdfcb..638b75f36e23 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -598,7 +598,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta; struct ieee80211_sub_if_data *sdata; - u16 start_seq_num = 0; + u16 start_seq_num; u8 *state; int ret; DECLARE_MAC_BUF(mac); @@ -678,6 +678,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) * call back right away, it must see that the flow has begun */ *state |= HT_ADDBA_REQUESTED_MSK; + /* This is slightly racy because the queue isn't stopped */ + start_seq_num = sta->tid_seq[tid]; + if (local->ops->ampdu_action) ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, ra, tid, &start_seq_num); -- cgit v1.2.3 From 9f1ba9062e032fb7b395cd27fc564754fe4e9867 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 7 Aug 2008 20:07:01 +0300 Subject: mac80211/cfg80211: Add BSS configuration options for AP mode This change adds a new cfg80211 command, NL80211_CMD_SET_BSS, to allow AP mode BSS parameters to be changed from user space (e.g., hostapd). The drivers using mac80211 are expected to be modified with separate changes to use the new BSS info parameter for short slot time in the bss_info_changed() handler. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 19 ++++++++++++++++++ include/net/cfg80211.h | 22 +++++++++++++++++++++ include/net/mac80211.h | 9 +++++++++ net/mac80211/cfg.c | 37 +++++++++++++++++++++++++++++++++++ net/wireless/nl80211.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+) (limited to 'net/mac80211') diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2be7c63bc0f2..447c02a5190e 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -89,6 +89,8 @@ * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC * or, if no MAC address given, all mesh paths, on the interface identified * by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by + * %NL80211_ATTR_IFINDEX. * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use @@ -127,6 +129,8 @@ enum nl80211_commands { NL80211_CMD_NEW_MPATH, NL80211_CMD_DEL_MPATH, + NL80211_CMD_SET_BSS, + /* add commands here */ /* used to define NL80211_CMD_MAX below */ @@ -134,6 +138,11 @@ enum nl80211_commands { NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 }; +/* + * Allow user space programs to use #ifdef on new commands by defining them + * here + */ +#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS /** * enum nl80211_attrs - nl80211 netlink attributes @@ -192,6 +201,12 @@ enum nl80211_commands { * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of * &enum nl80211_mntr_flags. * + * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled + * (u8, 0 or 1) + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -235,6 +250,10 @@ enum nl80211_attrs { NL80211_ATTR_MPATH_NEXT_HOP, NL80211_ATTR_MPATH_INFO, + NL80211_ATTR_BSS_CTS_PROT, + NL80211_ATTR_BSS_SHORT_PREAMBLE, + NL80211_ATTR_BSS_SHORT_SLOT_TIME, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e00750836ba5..7afef14d5c5b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -268,6 +268,23 @@ struct mpath_info { u8 flags; }; +/** + * struct bss_parameters - BSS parameters + * + * Used to change BSS parameters (mainly for AP mode). + * + * @use_cts_prot: Whether to use CTS protection + * (0 = no, 1 = yes, -1 = do not change) + * @use_short_preamble: Whether the use of short preambles is allowed + * (0 = no, 1 = yes, -1 = do not change) + * @use_short_slot_time: Whether the use of short slot time is allowed + * (0 = no, 1 = yes, -1 = do not change) + */ +struct bss_parameters { + int use_cts_prot; + int use_short_preamble; + int use_short_slot_time; +}; /* from net/wireless.h */ struct wiphy; @@ -318,6 +335,8 @@ struct wiphy; * @change_station: Modify a given station. * * @set_mesh_cfg: set mesh parameters (by now, just mesh id) + * + * @change_bss: Modify parameters for a given BSS. */ struct cfg80211_ops { int (*add_virtual_intf)(struct wiphy *wiphy, char *name, @@ -370,6 +389,9 @@ struct cfg80211_ops { int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo); + + int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, + struct bss_parameters *params); }; #endif /* __NET_CFG80211_H */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 0fdc3dabc964..7c399a9c11da 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -158,12 +158,14 @@ struct ieee80211_low_level_stats { * also implies a change in the AID. * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed * @BSS_CHANGED_ERP_PREAMBLE: preamble changed + * @BSS_CHANGED_ERP_SLOT: slot timing changed * @BSS_CHANGED_HT: 802.11n parameters changed */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, BSS_CHANGED_ERP_CTS_PROT = 1<<1, BSS_CHANGED_ERP_PREAMBLE = 1<<2, + BSS_CHANGED_ERP_SLOT = 1<<3, BSS_CHANGED_HT = 1<<4, }; @@ -177,6 +179,7 @@ enum ieee80211_bss_change { * @aid: association ID number, valid only when @assoc is true * @use_cts_prot: use CTS protection * @use_short_preamble: use 802.11b short preamble + * @use_short_slot: use short slot time (only relevant for ERP) * @dtim_period: num of beacons before the next DTIM, for PSM * @timestamp: beacon timestamp * @beacon_int: beacon interval @@ -192,6 +195,7 @@ struct ieee80211_bss_conf { /* erp related data */ bool use_cts_prot; bool use_short_preamble; + bool use_short_slot; u8 dtim_period; u16 beacon_int; u16 assoc_capability; @@ -420,6 +424,11 @@ struct ieee80211_rx_status { * @IEEE80211_CONF_PS: Enable 802.11 power save mode */ enum ieee80211_conf_flags { + /* + * TODO: IEEE80211_CONF_SHORT_SLOT_TIME will be removed once drivers + * have been converted to use bss_info_changed() for slot time + * configuration + */ IEEE80211_CONF_SHORT_SLOT_TIME = (1<<0), IEEE80211_CONF_RADIOTAP = (1<<1), IEEE80211_CONF_SUPPORT_HT_MODE = (1<<2), diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6d2ad2bf3ab5..2b19532f4c8a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1010,6 +1010,42 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, } #endif +static int ieee80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_sub_if_data *sdata; + u32 changed = 0; + + if (dev == local->mdev) + return -EOPNOTSUPP; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type != IEEE80211_IF_TYPE_AP) + return -EINVAL; + + if (params->use_cts_prot >= 0) { + sdata->bss_conf.use_cts_prot = params->use_cts_prot; + changed |= BSS_CHANGED_ERP_CTS_PROT; + } + if (params->use_short_preamble >= 0) { + sdata->bss_conf.use_short_preamble = + params->use_short_preamble; + changed |= BSS_CHANGED_ERP_PREAMBLE; + } + if (params->use_short_slot_time >= 0) { + sdata->bss_conf.use_short_slot = + params->use_short_slot_time; + changed |= BSS_CHANGED_ERP_SLOT; + } + + ieee80211_bss_info_change_notify(sdata, changed); + + return 0; +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1033,4 +1069,5 @@ struct cfg80211_ops mac80211_config_ops = { .get_mpath = ieee80211_get_mpath, .dump_mpath = ieee80211_dump_mpath, #endif + .change_bss = ieee80211_change_bss, }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 59eb2cf42e5f..47542ee01c57 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -87,6 +87,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY, .len = IEEE80211_MAX_MESH_ID_LEN }, [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, + + [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, + [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, + [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, }; /* message building helper */ @@ -1525,6 +1529,48 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) return err; } +static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *drv; + int err; + struct net_device *dev; + struct bss_parameters params; + + memset(¶ms, 0, sizeof(params)); + /* default to not changing parameters */ + params.use_cts_prot = -1; + params.use_short_preamble = -1; + params.use_short_slot_time = -1; + + if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) + params.use_cts_prot = + nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]); + if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) + params.use_short_preamble = + nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]); + if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) + params.use_short_slot_time = + nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); + + err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); + if (err) + return err; + + if (!drv->ops->change_bss) { + err = -EOPNOTSUPP; + goto out; + } + + rtnl_lock(); + err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); + rtnl_unlock(); + + out: + cfg80211_put_dev(drv); + dev_put(dev); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -1656,6 +1702,12 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_SET_BSS, + .doit = nl80211_set_bss, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; /* multicast groups */ -- cgit v1.2.3 From 43ac2ca3840f64f699a239535c590fa7ebaaac27 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 Aug 2008 22:21:27 +0300 Subject: mac80211: Handle scan result IEs in one block Clean up and extend scan result processing by storing all the IEs from Beacon/Probe Response frames in a single block instead of allocating memory for each specific IE separately. This removes lot of unnecessary code and automatically supports reporting of new IEs (e.g., IEEE 802.11r) into user space without need to manually extend mac80211 scanning code whenever a new protocol adds IE(s). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 18 ++-- net/mac80211/mlme.c | 230 ++++++++++++++++----------------------------- 2 files changed, 89 insertions(+), 159 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8361054fb7cf..2bb546744b94 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -79,16 +79,11 @@ struct ieee80211_sta_bss { enum ieee80211_band band; int freq; int signal, noise, qual; - u8 *wpa_ie; - size_t wpa_ie_len; - u8 *rsn_ie; - size_t rsn_ie_len; - u8 *wmm_ie; - size_t wmm_ie_len; - u8 *ht_ie; - size_t ht_ie_len; - u8 *ht_add_ie; - size_t ht_add_ie_len; + u8 *ies; /* all information elements from the last Beacon or Probe + * Response frames; note Beacon frame is not allowed to + * override values from Probe Response */ + size_t ies_len; + bool wmm_used; #ifdef CONFIG_MAC80211_MESH u8 *mesh_id; size_t mesh_id_len; @@ -773,6 +768,9 @@ struct ieee80211_ra_tid { /* Parsed Information Elements */ struct ieee802_11_elems { + u8 *ie_start; + size_t total_len; + /* pointers to IEs */ u8 *ssid; u8 *supp_rates; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 84999791a332..e088b440aafa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -98,6 +98,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, u8 *pos = start; memset(elems, 0, sizeof(*elems)); + elems->ie_start = start; + elems->total_len = len; while (left >= 2) { u8 id, elen; @@ -234,6 +236,27 @@ void ieee802_11_parse_elems(u8 *start, size_t len, } +static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) +{ + u8 *end, *pos; + + pos = bss->ies; + if (pos == NULL) + return NULL; + end = pos + bss->ies_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == ie) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + static int ecw2cw(int ecw) { return (1 << ecw) - 1; @@ -737,7 +760,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *ies; + u8 *pos, *ies, *ht_add_ie; int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_sta_bss *bss; @@ -772,7 +795,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; - if (bss->wmm_ie) + if (bss->wmm_used) wmm = 1; /* get all rates supported by the device and the AP as @@ -894,9 +917,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, /* wmm support is a must to HT */ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && - sband->ht_info.ht_supported && bss->ht_add_ie) { + sband->ht_info.ht_supported && + (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { struct ieee80211_ht_addt_info *ht_add_info = - (struct ieee80211_ht_addt_info *)bss->ht_add_ie; + (struct ieee80211_ht_addt_info *)ht_add_ie; u16 cap = sband->ht_info.cap; __le16 tmp; u32 flags = local->hw.conf.channel->flags; @@ -2372,11 +2396,7 @@ ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_i static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) { - kfree(bss->wpa_ie); - kfree(bss->rsn_ie); - kfree(bss->wmm_ie); - kfree(bss->ht_ie); - kfree(bss->ht_add_ie); + kfree(bss->ies); kfree(bss_mesh_id(bss)); kfree(bss_mesh_cfg(bss)); kfree(bss); @@ -2662,43 +2682,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bss->has_erp_value = 1; } - if (elems->ht_cap_elem && - (!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len || - memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) { - kfree(bss->ht_ie); - bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC); - if (bss->ht_ie) { - memcpy(bss->ht_ie, elems->ht_cap_elem - 2, - elems->ht_cap_elem_len + 2); - bss->ht_ie_len = elems->ht_cap_elem_len + 2; - } else - bss->ht_ie_len = 0; - } else if (!elems->ht_cap_elem && bss->ht_ie) { - kfree(bss->ht_ie); - bss->ht_ie = NULL; - bss->ht_ie_len = 0; - } - - if (elems->ht_info_elem && - (!bss->ht_add_ie || - bss->ht_add_ie_len != elems->ht_info_elem_len || - memcmp(bss->ht_add_ie, elems->ht_info_elem, - elems->ht_info_elem_len))) { - kfree(bss->ht_add_ie); - bss->ht_add_ie = - kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC); - if (bss->ht_add_ie) { - memcpy(bss->ht_add_ie, elems->ht_info_elem - 2, - elems->ht_info_elem_len + 2); - bss->ht_add_ie_len = elems->ht_info_elem_len + 2; - } else - bss->ht_add_ie_len = 0; - } else if (!elems->ht_info_elem && bss->ht_add_ie) { - kfree(bss->ht_add_ie); - bss->ht_add_ie = NULL; - bss->ht_add_ie_len = 0; - } - bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); @@ -2749,88 +2732,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, return; } - if (elems->wpa && - (!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len || - memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) { - kfree(bss->wpa_ie); - bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC); - if (bss->wpa_ie) { - memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2); - bss->wpa_ie_len = elems->wpa_len + 2; - } else - bss->wpa_ie_len = 0; - } else if (!elems->wpa && bss->wpa_ie) { - kfree(bss->wpa_ie); - bss->wpa_ie = NULL; - bss->wpa_ie_len = 0; - } - - if (elems->rsn && - (!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len || - memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) { - kfree(bss->rsn_ie); - bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC); - if (bss->rsn_ie) { - memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2); - bss->rsn_ie_len = elems->rsn_len + 2; - } else - bss->rsn_ie_len = 0; - } else if (!elems->rsn && bss->rsn_ie) { - kfree(bss->rsn_ie); - bss->rsn_ie = NULL; - bss->rsn_ie_len = 0; + if (bss->ies == NULL || bss->ies_len < elems->total_len) { + kfree(bss->ies); + bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); } + if (bss->ies) { + memcpy(bss->ies, elems->ie_start, elems->total_len); + bss->ies_len = elems->total_len; + } else + bss->ies_len = 0; - /* - * Cf. - * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC - * - * quoting: - * - * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia - * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi - * Alliance (September 1, 2004) is incorporated by reference herein. - * The inclusion of the WMM Parameters in probe responses and - * association responses is mandatory for WMM enabled networks. The - * inclusion of the WMM Parameters in beacons, however, is optional. - */ - - if (elems->wmm_param && - (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len || - memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) { - kfree(bss->wmm_ie); - bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC); - if (bss->wmm_ie) { - memcpy(bss->wmm_ie, elems->wmm_param - 2, - elems->wmm_param_len + 2); - bss->wmm_ie_len = elems->wmm_param_len + 2; - } else - bss->wmm_ie_len = 0; - } else if (elems->wmm_info && - (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len || - memcmp(bss->wmm_ie, elems->wmm_info, - elems->wmm_info_len))) { - /* As for certain AP's Fifth bit is not set in WMM IE in - * beacon frames.So while parsing the beacon frame the - * wmm_info structure is used instead of wmm_param. - * wmm_info structure was never used to set bss->wmm_ie. - * This code fixes this problem by copying the WME - * information from wmm_info to bss->wmm_ie and enabling - * n-band association. - */ - kfree(bss->wmm_ie); - bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC); - if (bss->wmm_ie) { - memcpy(bss->wmm_ie, elems->wmm_info - 2, - elems->wmm_info_len + 2); - bss->wmm_ie_len = elems->wmm_info_len + 2; - } else - bss->wmm_ie_len = 0; - } else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) { - kfree(bss->wmm_ie); - bss->wmm_ie = NULL; - bss->wmm_ie_len = 0; - } + bss->wmm_used = elems->wmm_param || elems->wmm_info; /* check if we need to merge IBSS */ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && @@ -4146,6 +4058,48 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t return 0; } + +static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, + struct ieee80211_sta_bss *bss, + char **current_ev, char *end_buf) +{ + u8 *pos, *end, *next; + struct iw_event iwe; + + if (bss == NULL || bss->ies == NULL) + return; + + /* + * If needed, fragment the IEs buffer (at IE boundaries) into short + * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. + */ + pos = bss->ies; + end = pos + bss->ies_len; + + while (end - pos > IW_GENERIC_IE_MAX) { + next = pos + 2 + pos[1]; + while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) + next = next + 2 + next[1]; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = next - pos; + *current_ev = iwe_stream_add_point(info, *current_ev, + end_buf, &iwe, pos); + + pos = next; + } + + if (end > pos) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = end - pos; + *current_ev = iwe_stream_add_point(info, *current_ev, + end_buf, &iwe, pos); + } +} + + static char * ieee80211_sta_scan_result(struct ieee80211_local *local, struct iw_request_info *info, @@ -4225,29 +4179,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); - if (bss && bss->wpa_ie) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->wpa_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->wpa_ie); - } - - if (bss && bss->rsn_ie) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->rsn_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->rsn_ie); - } - - if (bss && bss->ht_ie) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->ht_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ht_ie); - } + ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); if (bss && bss->supp_rates_len > 0) { /* display all supported rates in readable format */ -- cgit v1.2.3 From 2f58bbf27fe5321a7a208be9071efc54e8a8a3bd Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 19 Aug 2008 15:44:35 +0200 Subject: mac80211: Use only precedence level of DSCP field for frame classification Bit 4-5 of DSCP should not be considered by classify_d1. The 802.11 QoS Priority field is only depending on the precedence level. Signed-off-by: Daniel Wagner Signed-off-by: John W. Linville --- net/mac80211/wme.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 4310e2f65661..7229e958879d 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -47,8 +47,6 @@ static unsigned int classify_1d(struct sk_buff *skb) return 0; } - if (dscp & 0x1c) - return 0; return dscp >> 5; } -- cgit v1.2.3 From 36aedc903ea11a4188de0a118d26c9f20afdd272 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 Aug 2008 11:58:58 +0300 Subject: mac80211/cfg80211: HT capabilities for NEW_STA Allow userspace (e.g., hostapd) to set HT capabilities for associated STAs. This is based on a patch from Zhu Yi (only the NL80211_ATTR_HT_CAPABILITY for NEW_STA part is included here). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/linux/nl80211.h | 12 ++++++++++++ include/net/cfg80211.h | 1 + net/mac80211/cfg.c | 5 +++++ net/wireless/nl80211.c | 10 ++++++++++ 4 files changed, 28 insertions(+) (limited to 'net/mac80211') diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 447c02a5190e..0c1147de3ec7 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -207,6 +207,9 @@ enum nl80211_commands { * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled * (u8, 0 or 1) * + * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -254,16 +257,25 @@ enum nl80211_attrs { NL80211_ATTR_BSS_SHORT_PREAMBLE, NL80211_ATTR_BSS_SHORT_SLOT_TIME, + NL80211_ATTR_HT_CAPABILITY, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 }; +/* + * Allow user space programs to use #ifdef on new attributes by defining them + * here + */ +#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY + #define NL80211_MAX_SUPP_RATES 32 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 +#define NL80211_HT_CAPABILITY_LEN 26 /** * enum nl80211_iftype - (virtual) interface types diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7afef14d5c5b..0a72d1e3d3ab 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -152,6 +152,7 @@ struct station_parameters { u16 aid; u8 supported_rates_len; u8 plink_action; + struct ieee80211_ht_cap *ht_capa; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2b19532f4c8a..928813ce08e2 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -674,6 +674,11 @@ static void sta_apply_parameters(struct ieee80211_local *local, sta->supp_rates[local->oper_channel->band] = rates; } + if (params->ht_capa) { + ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, + &sta->ht_info); + } + if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { switch (params->plink_action) { case PLINK_ACTION_OPEN: diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 47542ee01c57..4d6c02afd6f5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -91,6 +91,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, + + [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, + .len = NL80211_HT_CAPABILITY_LEN }, }; /* message building helper */ @@ -1129,6 +1132,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) + params.ht_capa = + nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], ¶ms.station_flags)) return -EINVAL; @@ -1192,6 +1199,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) + params.ht_capa = + nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], ¶ms.station_flags)) -- cgit v1.2.3 From f59ac0481660e66cec67f1d6b024e78b9dc715fe Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 29 Aug 2008 16:26:43 -0700 Subject: cfg80211: keep track of supported interface modes It is obviously good for userspace to know up front which interface modes a given piece of hardware might support (even if adding such an interface might fail later because of concurrency issues), so let's make cfg80211 aware of that. For good measure, disallow adding interfaces in all other modes so drivers don't forget to announce support for one mode when they add it. Signed-off-by: Johannes Berg Signed-off-by: Stephen Blackheath Signed-off-by: Ivo van Doorn Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 1 + drivers/net/wireless/ath5k/base.c | 6 ++++++ drivers/net/wireless/ath9k/main.c | 5 +++++ drivers/net/wireless/b43/main.c | 7 +++++++ drivers/net/wireless/b43legacy/main.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +++++ drivers/net/wireless/mac80211_hwsim.c | 3 +++ drivers/net/wireless/p54/p54common.c | 3 +++ drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +++++ drivers/net/wireless/rtl8187_dev.c | 2 ++ drivers/net/wireless/zd1211rw/zd_mac.c | 5 +++++ include/linux/nl80211.h | 6 ++++++ include/net/wireless.h | 3 +++ net/mac80211/main.c | 7 +++++++ net/wireless/core.c | 9 ++++++++- net/wireless/nl80211.c | 22 ++++++++++++++++++++-- 17 files changed, 95 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 3333d4596b8d..c6a55cd12db9 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1884,6 +1884,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); dev->channel_change_time = 1000; dev->max_signal = 100; /* FIXME: find better value */ diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 7989ab5c2bba..85260c39aa2b 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -485,6 +485,12 @@ ath5k_pci_probe(struct pci_dev *pdev, hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + hw->extra_tx_headroom = 2; hw->channel_change_time = 5000; sc = hw->priv; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index dc45eef3289a..39a4a70d0130 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1482,6 +1482,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 63bafc2f3f0a..2d915c1a82a1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4569,6 +4569,13 @@ static int b43_wireless_init(struct ssb_device *dev) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); + hw->queues = b43_modparam_qos ? 4 : 1; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1cb77db5c292..68f63f5093af 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3704,6 +3704,11 @@ static int b43legacy_wireless_init(struct ssb_device *dev) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); hw->queues = 1; /* FIXME: hardware has more queues */ SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index fbf75a62958d..0a511ef8e354 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -819,6 +819,10 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; /* queues to support 11n aggregation */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a622fc33590a..cee3045f1606 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7888,6 +7888,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* 4 EDCA QOS priorities */ hw->queues = 4; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 732429d49122..6ba50f087f7b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -447,6 +447,9 @@ static int __init init_mac80211_hwsim(void) hw->channel_change_time = 1; hw->queues = 4; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP); hw->ampdu_queues = 1; memcpy(data->channels, hwsim_channels, sizeof(hwsim_channels)); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 17e06bbc996a..6da98e6e6a9a 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1072,6 +1072,9 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; + + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + dev->channel_change_time = 1000; /* TODO: find actual value */ dev->max_signal = 127; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 369b0b2d8643..2f3bfc606880 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1052,6 +1052,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); + rt2x00dev->hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + /* * Let the driver probe the device to detect the capabilities. */ diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 060a26505358..8a42bfa6d4f0 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -1184,6 +1184,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->max_signal = 65; } + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) printk(KERN_INFO "rtl8187: inconsistency between id with OEM" " info!\n"); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 4d7b98b05030..e019102b2285 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -937,6 +937,11 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_DB; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + hw->max_signal = 100; hw->queues = 1; hw->extra_tx_headroom = sizeof(struct zd_ctrlset); diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 0c1147de3ec7..5e51f4e7600b 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -210,6 +210,10 @@ enum nl80211_commands { * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from * association request when used with NL80211_CMD_NEW_STATION) * + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all + * supported interface types, each a flag attribute with the number + * of the interface mode. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -259,6 +263,8 @@ enum nl80211_attrs { NL80211_ATTR_HT_CAPABILITY, + NL80211_ATTR_SUPPORTED_IFTYPES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/wireless.h b/include/net/wireless.h index 9324f8dd183e..1dc8ec3daa2f 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -185,6 +185,9 @@ struct wiphy { /* permanent MAC address */ u8 perm_addr[ETH_ALEN]; + /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ + u16 interface_modes; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 638b75f36e23..396cfb2d0f46 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1675,6 +1675,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } } + /* if low-level driver supports AP, we also support VLAN */ + if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); + + /* mac80211 always supports monitor */ + local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); + result = wiphy_register(local->hw.wiphy); if (result < 0) return result; diff --git a/net/wireless/core.c b/net/wireless/core.c index f1da0b93bc56..7e995ac06a0c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1,7 +1,7 @@ /* * This is the linux wireless configuration interface. * - * Copyright 2006, 2007 Johannes Berg + * Copyright 2006-2008 Johannes Berg */ #include @@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy) struct ieee80211_supported_band *sband; bool have_band = false; int i; + u16 ifmodes = wiphy->interface_modes; + + /* sanity check ifmodes */ + WARN_ON(!ifmodes); + ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; + if (WARN_ON(ifmodes != wiphy->interface_modes)) + wiphy->interface_modes = ifmodes; /* sanity check supported bands/channels */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4d6c02afd6f5..77880ba8b619 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -113,10 +113,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct nlattr *nl_bands, *nl_band; struct nlattr *nl_freqs, *nl_freq; struct nlattr *nl_rates, *nl_rate; + struct nlattr *nl_modes; enum ieee80211_band band; struct ieee80211_channel *chan; struct ieee80211_rate *rate; int i; + u16 ifmodes = dev->wiphy.interface_modes; hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); if (!hdr) @@ -125,6 +127,20 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); + nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); + if (!nl_modes) + goto nla_put_failure; + + i = 0; + while (ifmodes) { + if (ifmodes & 1) + NLA_PUT_FLAG(msg, i); + ifmodes >>= 1; + i++; + } + + nla_nest_end(msg, nl_modes); + nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); if (!nl_bands) goto nla_put_failure; @@ -415,7 +431,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) ifindex = dev->ifindex; dev_put(dev); - if (!drv->ops->change_virtual_intf) { + if (!drv->ops->change_virtual_intf || + !(drv->wiphy.interface_modes & (1 << type))) { err = -EOPNOTSUPP; goto unlock; } @@ -462,7 +479,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(drv)) return PTR_ERR(drv); - if (!drv->ops->add_virtual_intf) { + if (!drv->ops->add_virtual_intf || + !(drv->wiphy.interface_modes & (1 << type))) { err = -EOPNOTSUPP; goto unlock; } -- cgit v1.2.3 From 9818babc8fd9a542978a235f1c1786f948cbac68 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 3 Sep 2008 23:42:19 +0300 Subject: mac80211: Fix low bit rate in IBSS This patch fixes regression in iwlwifi IBSS rate scaling caused by patch: commit 6bc37c06bc424bcf3f944e6a79e2d5bb537e02ed Author: Vladimir Koutny Date: Fri Jun 13 16:50:44 2008 +0200 mac80211: eliminate IBSS warning in rate_lowest_index() An IBSS station is added in prepare_for_handlers where the rate scaling was initialized only with single rate matching the received packet. The correct rate scale information should be updated only in ieee80211_rx_bss_info function where beacon is parsed. Because of coding error the rate info was left untouched. If a beacon has triggered the connection the rate remined 1Mbps. This patch fixes this coding error Signed-off-by: Tomas Winkler Cc: Vladimir Koutny Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7d53382f1a5b..75510a9f3f1d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2595,7 +2595,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, rx_status->band); prev_rates = sta->supp_rates[rx_status->band]; - sta->supp_rates[rx_status->band] &= supp_rates; + sta->supp_rates[rx_status->band] = supp_rates; if (sta->supp_rates[rx_status->band] == 0) { /* No matching rates - this should not really happen. * Make sure that at least one rate is marked -- cgit v1.2.3 From 8e1535d51bc93fbe9b3ded6555680044bc571d19 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 3 Sep 2008 23:42:20 +0300 Subject: mac80211: Fix rate scale initialization in IBSS This patch address some IBSS rate issues introduced or not covered by "mac80211: eliminate IBSS warning in rate_lowest_index()" and "cfg80211 API for channels/bitrates, mac80211 and driver conversion". This patch: 1. Moves addition of IBSS station from prepare_for_handlers to ieee80211_rx_bss_info when triggered from beacon eliminating bogus supported rates. 2. Initialize properly supported rates also in IBSS merging 3. Ensure that mandatory rates are always added into supported rates. This is needed in case when station addition is triggered from non beacon/probe packet. Some management frames need to be sent 4. Remove initialization of supported rates from self rates. This path was dead code after 6bc37c06bc4 and in general incorrect. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Cc: Vladimir Koutny Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 90 +++++++++++++++++++++++++++++++++++++---------------- net/mac80211/rx.c | 4 --- 2 files changed, 64 insertions(+), 30 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 75510a9f3f1d..c396c3522f7b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2557,6 +2557,33 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, return supp_rates; } +static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, + enum ieee80211_band band) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_rate *bitrates; + u64 mandatory_rates; + enum ieee80211_rate_flags mandatory_flag; + int i; + + sband = local->hw.wiphy->bands[band]; + if (!sband) { + WARN_ON(1); + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + } + + if (band == IEEE80211_BAND_2GHZ) + mandatory_flag = IEEE80211_RATE_MANDATORY_B; + else + mandatory_flag = IEEE80211_RATE_MANDATORY_A; + + bitrates = sband->bitrates; + mandatory_rates = 0; + for (i = 0; i < sband->n_bitrates; i++) + if (bitrates[i].flags & mandatory_flag) + mandatory_rates |= BIT(i); + return mandatory_rates; +} static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, @@ -2568,9 +2595,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, int freq, clen; struct ieee80211_sta_bss *bss; struct sta_info *sta; - u64 beacon_timestamp, rx_timestamp; struct ieee80211_channel *channel; + u64 beacon_timestamp, rx_timestamp; + u64 supp_rates = 0; bool beacon = ieee80211_is_beacon(mgmt->frame_control); + enum ieee80211_band band = rx_status->band; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); @@ -2578,30 +2607,41 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && elems->mesh_config && mesh_matches_local(elems, sdata)) { - u64 rates = ieee80211_sta_get_rates(local, elems, - rx_status->band); + supp_rates = ieee80211_sta_get_rates(local, elems, band); - mesh_neighbour_update(mgmt->sa, rates, sdata, + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, mesh_peer_accepts_plinks(elems)); } rcu_read_lock(); if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && - memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && - (sta = sta_info_get(local, mgmt->sa))) { - u64 prev_rates; - u64 supp_rates = ieee80211_sta_get_rates(local, elems, - rx_status->band); - - prev_rates = sta->supp_rates[rx_status->band]; - sta->supp_rates[rx_status->band] = supp_rates; - if (sta->supp_rates[rx_status->band] == 0) { - /* No matching rates - this should not really happen. - * Make sure that at least one rate is marked - * supported to avoid issues with TX rate ctrl. */ - sta->supp_rates[rx_status->band] = - sdata->u.sta.supp_rates_bits[rx_status->band]; + memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { + + supp_rates = ieee80211_sta_get_rates(local, elems, band); + + sta = sta_info_get(local, mgmt->sa); + if (sta) { + u64 prev_rates; + + prev_rates = sta->supp_rates[band]; + /* make sure mandatory rates are always added */ + sta->supp_rates[band] = supp_rates | + ieee80211_sta_get_mandatory_rates(local, band); + +#ifdef CONFIG_MAC80211_IBSS_DEBUG + if (sta->supp_rates[band] != prev_rates) + printk(KERN_DEBUG "%s: updated supp_rates set " + "for %s based on beacon info (0x%llx | " + "0x%llx -> 0x%llx)\n", + sdata->dev->name, print_mac(mac, sta->addr), + (unsigned long long) prev_rates, + (unsigned long long) supp_rates, + (unsigned long long) sta->supp_rates[band]); +#endif + } else { + ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, + mgmt->sa, supp_rates); } } @@ -2683,7 +2723,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bss->supp_rates_len += clen; } - bss->band = rx_status->band; + bss->band = band; bss->timestamp = beacon_timestamp; bss->last_update = jiffies; @@ -2738,7 +2778,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * e.g: at 1 MBit that means mactime is 192 usec earlier * (=24 bytes * 8 usecs/byte) than the beacon timestamp. */ - int rate = local->hw.wiphy->bands[rx_status->band]-> + int rate = local->hw.wiphy->bands[band]-> bitrates[rx_status->rate_idx].bitrate; rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); } else if (local && local->ops && local->ops->get_tsf) @@ -2766,7 +2806,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, mgmt->sa, - BIT(rx_status->rate_idx)); + supp_rates); } } @@ -3032,7 +3072,6 @@ void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff * kfree_skb(skb); } - static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { @@ -4316,10 +4355,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, set_sta_flags(sta, WLAN_STA_AUTHORIZED); - if (supp_rates) - sta->supp_rates[band] = supp_rates; - else - sta->supp_rates[band] = sdata->u.sta.supp_rates_bits[band]; + /* make sure mandatory rates are always added */ + sta->supp_rates[band] = supp_rates | + ieee80211_sta_get_mandatory_rates(local, band); rate_control_rate_init(sta, local); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fd83ef760a37..7e09b30dd393 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1743,10 +1743,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, if (!bssid) return 0; if (ieee80211_is_beacon(hdr->frame_control)) { - if (!rx->sta) - rx->sta = ieee80211_ibss_add_sta(sdata, - rx->skb, bssid, hdr->addr2, - BIT(rx->status->rate_idx)); return 1; } else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { -- cgit v1.2.3 From 701b9cb37bae3d50dbe5f345a7cdbd2648bf7df6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 4 Sep 2008 09:24:53 -0700 Subject: mac80211: add missing kernel-doc Fix mac80211 kernel-doc missing struct field: Warning(linux-2.6.27-rc1-git2//net/mac80211/sta_info.h:329): No description found for parameter 'tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]' Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville --- net/mac80211/sta_info.h | 1 + 1 file changed, 1 insertion(+) (limited to 'net/mac80211') diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 109db787ccb7..4a581a5b5766 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -204,6 +204,7 @@ struct sta_ampdu_mlme { * @tx_fragments: number of transmitted MPDUs * @txrate_idx: TBD * @last_txrate_idx: TBD + * @tid_seq: TBD * @wme_tx_queue: TBD * @ampdu_mlme: TBD * @timer_to_tid: identity mapping to ID timers -- cgit v1.2.3 From 00c5ae2fa0f8191a1b204e71f0ee11359e3b2c06 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 3 Sep 2008 11:26:42 +0800 Subject: mac80211: change MIMO_PS to SM_PS This patch follows 11n spec naming more rigorously replacing MIMO_PS with SM_PS (Spatial Multiplexing Power Save). (Originally submitted as 4 patches, "mac80211: change MIMO_PS to SM_PS", "iwlwifi: change MIMO_PS to SM_PS", "ath9k: change MIMO_PS to SM_PS", and "iwlwifi: remove double definition of SM PS". -- JWL) Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 16 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 ----- drivers/net/wireless/iwlwifi/iwl-sta.c | 8 ++++---- include/linux/ieee80211.h | 12 ++++++------ net/mac80211/main.c | 4 ++-- 8 files changed, 24 insertions(+), 29 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 245b7308a9ad..57d7cc87cb0f 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -224,7 +224,7 @@ static void setup_ht_cap(struct ieee80211_ht_info *ht_info) ht_info->ht_supported = 1; ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH - |(u16)IEEE80211_HT_CAP_MIMO_PS + |(u16)IEEE80211_HT_CAP_SM_PS |(u16)IEEE80211_HT_CAP_SGI_40 |(u16)IEEE80211_HT_CAP_DSSSCCK40; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 98f2c843b99e..4fc3a0f1d8f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1153,8 +1153,8 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, !sta->ht_info.ht_supported) return -1; - if (((sta->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS) >> 2) - == IWL_MIMO_PS_STATIC) + if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + == WLAN_HT_CAP_SM_PS_STATIC) return -1; /* Need both Tx chains/antennas to support MIMO */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1547122e66fa..27ddf6cb1c6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -564,7 +564,7 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, if (!iwl_conf->is_ht) return; - priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); + priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) iwl_conf->sgf |= HT_SHORT_GI_20MHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a0b86af25c83..789556db6842 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -399,8 +399,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20; - ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS & - (IWL_MIMO_PS_NONE << 2)); + ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS & + (WLAN_HT_CAP_SM_PS_DISABLED << 2)); max_bit_rate = MAX_BIT_RATE_20_MHZ; if (priv->hw_params.fat_channel & BIT(band)) { @@ -709,7 +709,7 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); /* # of Rx chains to use when expecting MIMO. */ - if (is_single || (!is_cam && (priv->ps_mode == IWL_MIMO_PS_STATIC))) + if (is_single || (!is_cam && (priv->ps_mode == WLAN_HT_CAP_SM_PS_STATIC))) return 2; else return 3; @@ -721,14 +721,14 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); /* # Rx chains when idling and maybe trying to save power */ switch (priv->ps_mode) { - case IWL_MIMO_PS_STATIC: - case IWL_MIMO_PS_DYNAMIC: + case WLAN_HT_CAP_SM_PS_STATIC: + case WLAN_HT_CAP_SM_PS_DYNAMIC: idle_cnt = (is_cam) ? 2 : 1; break; - case IWL_MIMO_PS_NONE: + case WLAN_HT_CAP_SM_PS_DISABLED: idle_cnt = (is_cam) ? active_cnt : 1; break; - case IWL_MIMO_PS_INVALID: + case WLAN_HT_CAP_SM_PS_INVALID: default: IWL_ERROR("invalide mimo ps mode %d\n", priv->ps_mode); WARN_ON(1); @@ -912,7 +912,7 @@ int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = IEEE80211_IF_TYPE_STA; priv->use_ant_b_for_management_frame = 1; /* start with ant B */ - priv->ps_mode = IWL_MIMO_PS_NONE; + priv->ps_mode = WLAN_HT_CAP_SM_PS_DISABLED; /* Choose which receivers/antennas to use */ iwl_set_rxon_chain(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 640ceea913c7..f302e93b7798 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -644,11 +644,6 @@ struct iwl_kw { #define IWL_CHANNEL_WIDTH_20MHZ 0 #define IWL_CHANNEL_WIDTH_40MHZ 1 -#define IWL_MIMO_PS_STATIC 0 -#define IWL_MIMO_PS_NONE 3 -#define IWL_MIMO_PS_DYNAMIC 1 -#define IWL_MIMO_PS_INVALID 2 - #define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_HT_ONLY 1 #define IWL_OPERATION_MODE_MIXED 2 diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5b7b05c8773f..a72569f1acb5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -191,20 +191,20 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, if (!sta_ht_inf || !sta_ht_inf->ht_supported) goto done; - mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2; + mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; sta_flags = priv->stations[index].sta.station_flags; sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK); switch (mimo_ps_mode) { - case WLAN_HT_CAP_MIMO_PS_STATIC: + case WLAN_HT_CAP_SM_PS_STATIC: sta_flags |= STA_FLG_MIMO_DIS_MSK; break; - case WLAN_HT_CAP_MIMO_PS_DYNAMIC: + case WLAN_HT_CAP_SM_PS_DYNAMIC: sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK; break; - case WLAN_HT_CAP_MIMO_PS_DISABLED: + case WLAN_HT_CAP_SM_PS_DISABLED: break; default: IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index be456450cd2e..333d3ae76883 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -708,7 +708,7 @@ struct ieee80211_ht_addt_info { /* 802.11n HT capabilities masks */ #define IEEE80211_HT_CAP_SUP_WIDTH 0x0002 -#define IEEE80211_HT_CAP_MIMO_PS 0x000C +#define IEEE80211_HT_CAP_SM_PS 0x000C #define IEEE80211_HT_CAP_GRN_FLD 0x0010 #define IEEE80211_HT_CAP_SGI_20 0x0020 #define IEEE80211_HT_CAP_SGI_40 0x0040 @@ -737,11 +737,11 @@ struct ieee80211_ht_addt_info { #define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004 #define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010 -/* MIMO Power Save Modes */ -#define WLAN_HT_CAP_MIMO_PS_STATIC 0 -#define WLAN_HT_CAP_MIMO_PS_DYNAMIC 1 -#define WLAN_HT_CAP_MIMO_PS_INVALID 2 -#define WLAN_HT_CAP_MIMO_PS_DISABLED 3 +/* Spatial Multiplexing Power Save Modes */ +#define WLAN_HT_CAP_SM_PS_STATIC 0 +#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 +#define WLAN_HT_CAP_SM_PS_INVALID 2 +#define WLAN_HT_CAP_SM_PS_DISABLED 3 /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 396cfb2d0f46..7dc063197259 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1140,8 +1140,8 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, ht_conf.ht_supported = 1; ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; - ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); - ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; + ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS); + ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS; ht_bss_conf.primary_channel = req_bss_cap->primary_channel; ht_bss_conf.bss_cap = req_bss_cap->bss_cap; ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; -- cgit v1.2.3 From 69e6c010fd5f5015d3cc64718fbe266face93770 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 11:05:08 +0200 Subject: mac80211: move some RCU locking into an if branch The if itself doesn't need to be protected, so move in the RCU locking to avoid doing anything at all when the condition isn't true. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index df12e746b03e..0abd5a4fe38d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2612,13 +2612,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, mesh_peer_accepts_plinks(elems)); } - rcu_read_lock(); - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { - supp_rates = ieee80211_sta_get_rates(local, elems, band); + rcu_read_lock(); + sta = sta_info_get(local, mgmt->sa); if (sta) { u64 prev_rates; @@ -2642,9 +2641,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, mgmt->sa, supp_rates); } - } - rcu_read_unlock(); + rcu_read_unlock(); + } if (elems->ds_params && elems->ds_params_len == 1) freq = ieee80211_channel_to_frequency(elems->ds_params[0]); -- cgit v1.2.3 From fe3fa827314b877486c515a001c3e6f604f6f16f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 11:05:09 +0200 Subject: mac80211: make conf_tx non-atomic The conf_tx callback currently needs to be atomic, this requirement is just because it can be called from scanning. This rearranges it slightly to only update while not scanning (which is fine, we'll be getting beacons when associated) and thus removes the atomic requirement. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 +- net/mac80211/mlme.c | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7c399a9c11da..fb9e62211c34 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1142,7 +1142,7 @@ enum ieee80211_ampdu_mlme_action { * of assocaited station or AP. * * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), - * bursting) for a hardware TX queue. Must be atomic. + * bursting) for a hardware TX queue. * * @get_tx_stats: Get statistics of the current TX queue status. This is used * to get number of currently queued packets (queue length), maximum queue diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0abd5a4fe38d..a03245255ed0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2872,15 +2872,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, - elems.wmm_param_len); - /* Do not send changes to driver if we are scanning. This removes - * requirement that driver's bss_info_changed function needs to be - * atomic. */ + * requirement that a driver's bss_info_changed/conf_tx functions + * need to be atomic. + * This is really ugly code, we should rewrite scanning and make + * all this more understandable for humans. + */ if (local->sta_sw_scanning || local->sta_hw_scanning) return; + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, + elems.wmm_param_len); + if (elems.erp_info && elems.erp_info_len >= 1) changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); else { -- cgit v1.2.3 From 5bda617576e58c7213aef5ab90383f303727b5b1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 11:05:10 +0200 Subject: mac80211: BSS info: check channel first When we receive information about a BSS we check at some point whether or not we think we're allowed to use the channel it is on, but we do that fairly late. I don't think we should do it that late, so do it earlier to avoid doing IBSS/mesh stuff on that channel and then getting confused because it's disabled. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a03245255ed0..ae97d7e9945d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2602,7 +2602,15 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); - beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); + if (elems->ds_params && elems->ds_params_len == 1) + freq = ieee80211_channel_to_frequency(elems->ds_params[0]); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(local->hw.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) + return; if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && elems->mesh_config && mesh_matches_local(elems, sdata)) { @@ -2645,16 +2653,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); } - if (elems->ds_params && elems->ds_params_len == 1) - freq = ieee80211_channel_to_frequency(elems->ds_params[0]); - else - freq = rx_status->freq; - - channel = ieee80211_get_channel(local->hw.wiphy, freq); - - if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) - return; - #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, @@ -2723,6 +2721,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bss->band = band; + beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); + bss->timestamp = beacon_timestamp; bss->last_update = jiffies; bss->signal = rx_status->signal; -- cgit v1.2.3 From 9c80d3dc272ec5ce44a7564e5392f950ad38357a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 15:41:59 +0200 Subject: mac80211: fix action frame length checks The action frame length checks are one too small, there's not just an action code as the comment makes you believe, there's a category code too, and the category code is required in each action frame (hence part of IEEE80211_MIN_ACTION_SIZE). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mesh_hwmp.c | 4 ++++ net/mac80211/mesh_plink.c | 4 ++++ net/mac80211/mlme.c | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index eeb0ce2d5d37..59fd7fe377e0 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -581,6 +581,10 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, size_t baselen; u32 last_hop_metric; + /* need action_code */ + if (len < IEEE80211_MIN_ACTION_SIZE + 1) + return; + baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, len - baselen, &elems); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7714b0e6e4d7..74983cfa7293 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -421,6 +421,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m DECLARE_MAC_BUF(mac); #endif + /* need action_code, aux */ + if (len < IEEE80211_MIN_ACTION_SIZE + 3) + return; + if (is_multicast_ether_addr(mgmt->da)) { mpl_dbg("Mesh plink: ignore frame from multicast address"); return; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ae97d7e9945d..eb1832aa1fe5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -60,7 +60,7 @@ #define ERP_INFO_USE_PROTECTION BIT(1) -/* mgmt header + 1 byte action code */ +/* mgmt header + 1 byte category code */ #define IEEE80211_MIN_ACTION_SIZE (24 + 1) #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 @@ -2988,7 +2988,8 @@ static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; - if (len < IEEE80211_MIN_ACTION_SIZE) + /* all categories we currently handle have action_code */ + if (len < IEEE80211_MIN_ACTION_SIZE + 1) return; switch (mgmt->u.action.category) { -- cgit v1.2.3 From 5fd12d4da198647e834f93f163e20bfcdd33bad8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 16:31:48 +0200 Subject: mac80211: fix typo in action frame handling This says chan_switch.action_code but really means measurement.action_code, of course the actual offset in the frame is the same, it's just harder to understand this way. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index eb1832aa1fe5..2341e5b3c248 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2996,7 +2996,7 @@ static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, case WLAN_CATEGORY_SPECTRUM_MGMT: if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) break; - switch (mgmt->u.action.u.chan_switch.action_code) { + switch (mgmt->u.action.u.measurement.action_code) { case WLAN_ACTION_SPCT_MSR_REQ: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.measurement))) -- cgit v1.2.3 From 37ffc8da803a1151e887f2a80f08f0c49d1dc1d5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 16:40:36 +0200 Subject: mac80211: move IE parsing to util file Since IE parsing is required for the mlme and mesh code, it's not a static function anyway, and it's much better to have it in util rather than the overly large mlme.c Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 145 ---------------------------------------------------- net/mac80211/util.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 145 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2341e5b3c248..b03f1f3ef2ed 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -91,151 +91,6 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, static void sta_rx_agg_session_timer_expired(unsigned long data); -void ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems) -{ - size_t left = len; - u8 *pos = start; - - memset(elems, 0, sizeof(*elems)); - elems->ie_start = start; - elems->total_len = len; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) - return; - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_WPA: - if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && - pos[2] == 0xf2) { - /* Microsoft OUI (00:50:F2) */ - if (pos[3] == 1) { - /* OUI Type 1 - WPA IE */ - elems->wpa = pos; - elems->wpa_len = elen; - } else if (elen >= 5 && pos[3] == 2) { - if (pos[4] == 0) { - elems->wmm_info = pos; - elems->wmm_info_len = elen; - } else if (pos[4] == 1) { - elems->wmm_param = pos; - elems->wmm_param_len = elen; - } - } - } - break; - case WLAN_EID_RSN: - elems->rsn = pos; - elems->rsn_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_HT_CAPABILITY: - elems->ht_cap_elem = pos; - elems->ht_cap_elem_len = elen; - break; - case WLAN_EID_HT_EXTRA_INFO: - elems->ht_info_elem = pos; - elems->ht_info_elem_len = elen; - break; - case WLAN_EID_MESH_ID: - elems->mesh_id = pos; - elems->mesh_id_len = elen; - break; - case WLAN_EID_MESH_CONFIG: - elems->mesh_config = pos; - elems->mesh_config_len = elen; - break; - case WLAN_EID_PEER_LINK: - elems->peer_link = pos; - elems->peer_link_len = elen; - break; - case WLAN_EID_PREQ: - elems->preq = pos; - elems->preq_len = elen; - break; - case WLAN_EID_PREP: - elems->prep = pos; - elems->prep_len = elen; - break; - case WLAN_EID_PERR: - elems->perr = pos; - elems->perr_len = elen; - break; - case WLAN_EID_CHANNEL_SWITCH: - elems->ch_switch_elem = pos; - elems->ch_switch_elem_len = elen; - break; - case WLAN_EID_QUIET: - if (!elems->quiet_elem) { - elems->quiet_elem = pos; - elems->quiet_elem_len = elen; - } - elems->num_of_quiet_elem++; - break; - case WLAN_EID_COUNTRY: - elems->country_elem = pos; - elems->country_elem_len = elen; - break; - case WLAN_EID_PWR_CONSTRAINT: - elems->pwr_constr_elem = pos; - elems->pwr_constr_elem_len = elen; - break; - default: - break; - } - - left -= elen; - pos += elen; - } -} - - static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) { u8 *end, *pos; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f40c060341ae..e19c74cada39 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -428,3 +428,147 @@ void ieee80211_iterate_active_interfaces_atomic( rcu_read_unlock(); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); + +void ieee802_11_parse_elems(u8 *start, size_t len, + struct ieee802_11_elems *elems) +{ + size_t left = len; + u8 *pos = start; + + memset(elems, 0, sizeof(*elems)); + elems->ie_start = start; + elems->total_len = len; + + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) + return; + + switch (id) { + case WLAN_EID_SSID: + elems->ssid = pos; + elems->ssid_len = elen; + break; + case WLAN_EID_SUPP_RATES: + elems->supp_rates = pos; + elems->supp_rates_len = elen; + break; + case WLAN_EID_FH_PARAMS: + elems->fh_params = pos; + elems->fh_params_len = elen; + break; + case WLAN_EID_DS_PARAMS: + elems->ds_params = pos; + elems->ds_params_len = elen; + break; + case WLAN_EID_CF_PARAMS: + elems->cf_params = pos; + elems->cf_params_len = elen; + break; + case WLAN_EID_TIM: + elems->tim = pos; + elems->tim_len = elen; + break; + case WLAN_EID_IBSS_PARAMS: + elems->ibss_params = pos; + elems->ibss_params_len = elen; + break; + case WLAN_EID_CHALLENGE: + elems->challenge = pos; + elems->challenge_len = elen; + break; + case WLAN_EID_WPA: + if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && + pos[2] == 0xf2) { + /* Microsoft OUI (00:50:F2) */ + if (pos[3] == 1) { + /* OUI Type 1 - WPA IE */ + elems->wpa = pos; + elems->wpa_len = elen; + } else if (elen >= 5 && pos[3] == 2) { + if (pos[4] == 0) { + elems->wmm_info = pos; + elems->wmm_info_len = elen; + } else if (pos[4] == 1) { + elems->wmm_param = pos; + elems->wmm_param_len = elen; + } + } + } + break; + case WLAN_EID_RSN: + elems->rsn = pos; + elems->rsn_len = elen; + break; + case WLAN_EID_ERP_INFO: + elems->erp_info = pos; + elems->erp_info_len = elen; + break; + case WLAN_EID_EXT_SUPP_RATES: + elems->ext_supp_rates = pos; + elems->ext_supp_rates_len = elen; + break; + case WLAN_EID_HT_CAPABILITY: + elems->ht_cap_elem = pos; + elems->ht_cap_elem_len = elen; + break; + case WLAN_EID_HT_EXTRA_INFO: + elems->ht_info_elem = pos; + elems->ht_info_elem_len = elen; + break; + case WLAN_EID_MESH_ID: + elems->mesh_id = pos; + elems->mesh_id_len = elen; + break; + case WLAN_EID_MESH_CONFIG: + elems->mesh_config = pos; + elems->mesh_config_len = elen; + break; + case WLAN_EID_PEER_LINK: + elems->peer_link = pos; + elems->peer_link_len = elen; + break; + case WLAN_EID_PREQ: + elems->preq = pos; + elems->preq_len = elen; + break; + case WLAN_EID_PREP: + elems->prep = pos; + elems->prep_len = elen; + break; + case WLAN_EID_PERR: + elems->perr = pos; + elems->perr_len = elen; + break; + case WLAN_EID_CHANNEL_SWITCH: + elems->ch_switch_elem = pos; + elems->ch_switch_elem_len = elen; + break; + case WLAN_EID_QUIET: + if (!elems->quiet_elem) { + elems->quiet_elem = pos; + elems->quiet_elem_len = elen; + } + elems->num_of_quiet_elem++; + break; + case WLAN_EID_COUNTRY: + elems->country_elem = pos; + elems->country_elem_len = elen; + break; + case WLAN_EID_PWR_CONSTRAINT: + elems->pwr_constr_elem = pos; + elems->pwr_constr_elem_len = elen; + break; + default: + break; + } + + left -= elen; + pos += elen; + } +} -- cgit v1.2.3 From aa458d1737c3cc9a7c90ea9c5ef1ee6d663fba71 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 9 Sep 2008 00:32:12 +0300 Subject: mac80211: restructure disassoc/deauth flows This patch restructure the flow of disassociation and deauthentication flows to be consistent under all circumstances. It ensures that BA session is treated down before deauthentication or disassociation, adds the removal of the obsolete sta form station table and fixes a related bug (sta_info_destroy without sta_info_unlink) in ieee80211_associated() and reduce some code duplication Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 85 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 31 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b03f1f3ef2ed..f7a390ff9679 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -415,8 +415,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); ieee80211_sta_send_associnfo(sdata, ifsta); } else { - netif_carrier_off(sdata->dev); - ieee80211_sta_tear_down_BA_sessions(sdata, ifsta->bssid); ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; changed |= ieee80211_reset_erp_info(sdata); @@ -439,18 +437,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); } -static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, int deauth) -{ - if (deauth) { - ifsta->direct_probe_tries = 0; - ifsta->auth_tries = 0; - } - ifsta->assoc_scan_tries = 0; - ifsta->assoc_tries = 0; - ieee80211_set_associated(sdata, ifsta, 0); -} - void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt) { @@ -844,6 +830,50 @@ static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tx(sdata, skb, 0); } +static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta, bool deauth, + bool self_disconnected, u16 reason) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + + rcu_read_lock(); + + sta = sta_info_get(local, ifsta->bssid); + if (!sta) { + rcu_read_unlock(); + return; + } + + if (deauth) { + ifsta->direct_probe_tries = 0; + ifsta->auth_tries = 0; + } + ifsta->assoc_scan_tries = 0; + ifsta->assoc_tries = 0; + + netif_carrier_off(sdata->dev); + + ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); + + if (self_disconnected) { + if (deauth) + ieee80211_send_deauth(sdata, ifsta, reason); + else + ieee80211_send_disassoc(sdata, ifsta, reason); + } + + ieee80211_set_associated(sdata, ifsta, 0); + + if (self_disconnected) + ifsta->state = IEEE80211_STA_MLME_DISABLED; + + sta_info_unlink(&sta); + + rcu_read_unlock(); + + sta_info_destroy(sta); +} static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) @@ -938,7 +968,6 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, "range\n", sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; - sta_info_unlink(&sta); } else ieee80211_send_probe_req(sdata, ifsta->bssid, local->scan_ssid, @@ -958,16 +987,12 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - if (disassoc && sta) - sta_info_destroy(sta); - - if (disassoc) { - ifsta->state = IEEE80211_STA_MLME_DISABLED; - ieee80211_set_associated(sdata, ifsta, 0); - } else { + if (disassoc) + ieee80211_set_disassoc(sdata, ifsta, true, true, + WLAN_REASON_PREV_AUTH_NOT_VALID); + else mod_timer(&ifsta->timer, jiffies + IEEE80211_MONITORING_INTERVAL); - } } @@ -1832,7 +1857,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(sdata, ifsta, 1); + ieee80211_set_disassoc(sdata, ifsta, true, false, 0); ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; } @@ -1862,7 +1887,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(sdata, ifsta, 0); + ieee80211_set_disassoc(sdata, ifsta, false, false, 0); } @@ -3200,8 +3225,8 @@ void ieee80211_sta_work(struct work_struct *work) printk(KERN_DEBUG "%s: privacy configuration mismatch and " "mixed-cell disabled - disassociate\n", sdata->dev->name); - ieee80211_send_disassoc(sdata, ifsta, WLAN_REASON_UNSPECIFIED); - ieee80211_set_disassoc(sdata, ifsta, 0); + ieee80211_set_disassoc(sdata, ifsta, false, true, + WLAN_REASON_UNSPECIFIED); } } @@ -4236,8 +4261,7 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return -EINVAL; - ieee80211_send_deauth(sdata, ifsta, reason); - ieee80211_set_disassoc(sdata, ifsta, 1); + ieee80211_set_disassoc(sdata, ifsta, true, true, reason); return 0; } @@ -4255,8 +4279,7 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) return -1; - ieee80211_send_disassoc(sdata, ifsta, reason); - ieee80211_set_disassoc(sdata, ifsta, 0); + ieee80211_set_disassoc(sdata, ifsta, false, true, reason); return 0; } -- cgit v1.2.3 From 3b7ee69d0caefbdb85a606a98bff841b8c63b97e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 8 Sep 2008 17:33:38 +0200 Subject: mac80211: disassociate when moving to new BSS This patch makes the MLME cleanly disassociate from the current BSS when leaving it for a new one. This is not just nicer to the old AP (we're leaving it, might as well tell it!) but also required for some drivers that keep track of the station we're associated with, they'd get confused because they'd think we are associated with two APs. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f7a390ff9679..eababf320b83 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3271,9 +3271,14 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, return; if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | - IEEE80211_STA_AUTO_BSSID_SEL)) && + IEEE80211_STA_AUTO_BSSID_SEL)) && (ifsta->flags & (IEEE80211_STA_SSID_SET | - IEEE80211_STA_AUTO_SSID_SEL))) { + IEEE80211_STA_AUTO_SSID_SEL))) { + + if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) + ieee80211_set_disassoc(sdata, ifsta, true, true, + WLAN_REASON_DEAUTH_LEAVING); + set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); queue_work(local->hw.workqueue, &ifsta->work); } -- cgit v1.2.3 From f5e5bf258b399f74b606e532ae0a2599522fd7bf Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 8 Sep 2008 17:33:39 +0200 Subject: mac80211: remove disassociation code from ieee80211_set_associated This patch moves disassociation code from ieee80211_set_associated to ieee80211_set_disassoc. To reduce code duplication, it introduces the ieee80211_sta_send_apinfo function. Additionally, it fixes a lapse where BSS_CHANGED_HT wasn't set when notifying the driver of changes due to disassociation. Signed-off-by: Tomas Winkler Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 102 ++++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 46 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index eababf320b83..0e9bd840e7dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -352,6 +352,17 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( return 0; } +static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) +{ + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + if (ifsta->flags & IEEE80211_STA_ASSOCIATED) + memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); +} + static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -373,68 +384,53 @@ static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, - bool assoc) + struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local_to_hw(local)->conf; - union iwreq_data wrqu; u32 changed = BSS_CHANGED_ASSOC; - if (assoc) { - struct ieee80211_sta_bss *bss; - - ifsta->flags |= IEEE80211_STA_ASSOCIATED; + struct ieee80211_sta_bss *bss; - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return; + ifsta->flags |= IEEE80211_STA_ASSOCIATED; - bss = ieee80211_rx_bss_get(local, ifsta->bssid, - conf->channel->center_freq, - ifsta->ssid, ifsta->ssid_len); - if (bss) { - /* set timing information */ - sdata->bss_conf.beacon_int = bss->beacon_int; - sdata->bss_conf.timestamp = bss->timestamp; - sdata->bss_conf.dtim_period = bss->dtim_period; + if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + return; - changed |= ieee80211_handle_bss_capability(sdata, bss); + bss = ieee80211_rx_bss_get(local, ifsta->bssid, + conf->channel->center_freq, + ifsta->ssid, ifsta->ssid_len); + if (bss) { + /* set timing information */ + sdata->bss_conf.beacon_int = bss->beacon_int; + sdata->bss_conf.timestamp = bss->timestamp; + sdata->bss_conf.dtim_period = bss->dtim_period; - ieee80211_rx_bss_put(local, bss); - } + changed |= ieee80211_handle_bss_capability(sdata, bss); - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { - changed |= BSS_CHANGED_HT; - sdata->bss_conf.assoc_ht = 1; - sdata->bss_conf.ht_conf = &conf->ht_conf; - sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; - } + ieee80211_rx_bss_put(local, bss); + } - ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; - memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); - memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_send_associnfo(sdata, ifsta); - } else { - ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - changed |= ieee80211_reset_erp_info(sdata); + if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + changed |= BSS_CHANGED_HT; + sdata->bss_conf.assoc_ht = 1; + sdata->bss_conf.ht_conf = &conf->ht_conf; + sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; + } - sdata->bss_conf.assoc_ht = 0; - sdata->bss_conf.ht_conf = NULL; - sdata->bss_conf.ht_bss_conf = NULL; + ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; + memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); + ieee80211_sta_send_associnfo(sdata, ifsta); - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - } ifsta->last_probe = jiffies; - ieee80211_led_assoc(local, assoc); + ieee80211_led_assoc(local, 1); - sdata->bss_conf.assoc = assoc; + sdata->bss_conf.assoc = 1; ieee80211_bss_info_change_notify(sdata, changed); - if (assoc) - netif_carrier_on(sdata->dev); + netif_carrier_on(sdata->dev); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); + ieee80211_sta_send_apinfo(sdata, ifsta); } void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, @@ -836,6 +832,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct sta_info *sta; + u32 changed = BSS_CHANGED_ASSOC; rcu_read_lock(); @@ -863,7 +860,20 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_send_disassoc(sdata, ifsta, reason); } - ieee80211_set_associated(sdata, ifsta, 0); + ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; + changed |= ieee80211_reset_erp_info(sdata); + + if (sdata->bss_conf.assoc_ht) + changed |= BSS_CHANGED_HT; + + sdata->bss_conf.assoc_ht = 0; + sdata->bss_conf.ht_conf = NULL; + sdata->bss_conf.ht_bss_conf = NULL; + + ieee80211_led_assoc(local, 0); + sdata->bss_conf.assoc = 0; + + ieee80211_sta_send_apinfo(sdata, ifsta); if (self_disconnected) ifsta->state = IEEE80211_STA_MLME_DISABLED; @@ -2081,7 +2091,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * ieee80211_set_associated() will tell the driver */ bss_conf->aid = aid; bss_conf->assoc_capability = capab_info; - ieee80211_set_associated(sdata, ifsta, 1); + ieee80211_set_associated(sdata, ifsta); ieee80211_associated(sdata, ifsta); } -- cgit v1.2.3 From 24e64622c3f3143c801850897ab0cea8f3c69445 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 8 Sep 2008 17:33:40 +0200 Subject: mac80211: stop queues before carrier off During testing of the disassociation fixes, Tomas noticed that it was possible to run into a situation where you'd suddenly get a few "wlan0: dropped frame to (unauthorized port)" messages and I found this to be due to the AP's sta_info having been removed but netif_carrier_off not having removed/stopped traffic yet. To avoid that, stop the queue for the interface (and avoid bringing them up when another vif scans when they weren't up.) Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0e9bd840e7dd..d889e2a89e4b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -428,6 +428,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->bss_conf.assoc = 1; ieee80211_bss_info_change_notify(sdata, changed); + netif_tx_start_all_queues(sdata->dev); netif_carrier_on(sdata->dev); ieee80211_sta_send_apinfo(sdata, ifsta); @@ -849,6 +850,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ifsta->assoc_scan_tries = 0; ifsta->assoc_tries = 0; + netif_tx_stop_all_queues(sdata->dev); netif_carrier_off(sdata->dev); ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); @@ -3268,6 +3270,7 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, ifsta->direct_probe_tries = 0; ifsta->auth_tries = 0; ifsta->assoc_tries = 0; + netif_tx_stop_all_queues(sdata->dev); netif_carrier_off(sdata->dev); } @@ -3744,13 +3747,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { /* Tell AP we're back */ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA && - sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) - ieee80211_send_nullfunc(local, sdata, 0); + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { + ieee80211_send_nullfunc(local, sdata, 0); + netif_tx_wake_all_queues(sdata->dev); + } + } else + netif_tx_wake_all_queues(sdata->dev); ieee80211_restart_sta_timer(sdata); - - netif_wake_queue(sdata->dev); } rcu_read_unlock(); @@ -3908,10 +3913,13 @@ static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - netif_stop_queue(sdata->dev); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA && - (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) - ieee80211_send_nullfunc(local, sdata, 1); + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { + netif_tx_stop_all_queues(sdata->dev); + ieee80211_send_nullfunc(local, sdata, 1); + } + } else + netif_tx_stop_all_queues(sdata->dev); } rcu_read_unlock(); -- cgit v1.2.3 From 60f8b39c9406752ea5e0d3bbf5df6f903d61cacf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:22 +0200 Subject: mac80211: reorder mlme code This reorders the mlme code a bit so we don't need all the forward function declarations. It also removes the ERP_INFO_USE_PROTECTION define that is unused, but otherwise contains no real changes. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 1224 +++++++++++++++++++++++++-------------------------- 1 file changed, 597 insertions(+), 627 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d889e2a89e4b..67c38235a3c5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -26,9 +26,8 @@ #include #include #include -#include - #include + #include "ieee80211_i.h" #include "rate.h" #include "led.h" @@ -58,8 +57,6 @@ #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 -#define ERP_INFO_USE_PROTECTION BIT(1) - /* mgmt header + 1 byte category code */ #define IEEE80211_MIN_ACTION_SIZE (24 + 1) @@ -74,24 +71,199 @@ #define IEEE80211_MIN_AMPDU_BUF 0x8 #define IEEE80211_MAX_AMPDU_BUF 0x40 -static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len); +/* BSS handling */ static struct ieee80211_sta_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len); + u8 *ssid, u8 ssid_len) +{ + struct ieee80211_sta_bss *bss; + + spin_lock_bh(&local->sta_bss_lock); + bss = local->sta_bss_hash[STA_HASH(bssid)]; + while (bss) { + if (!bss_mesh_cfg(bss) && + !memcmp(bss->bssid, bssid, ETH_ALEN) && + bss->freq == freq && + bss->ssid_len == ssid_len && + (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { + atomic_inc(&bss->users); + break; + } + bss = bss->hnext; + } + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} + +/* Caller must hold local->sta_bss_lock */ +static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss) +{ + u8 hash_idx; + + if (bss_mesh_cfg(bss)) + hash_idx = mesh_id_hash(bss_mesh_id(bss), + bss_mesh_id_len(bss)); + else + hash_idx = STA_HASH(bss->bssid); + + bss->hnext = local->sta_bss_hash[hash_idx]; + local->sta_bss_hash[hash_idx] = bss; +} + +/* Caller must hold local->sta_bss_lock */ +static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss) +{ + struct ieee80211_sta_bss *b, *prev = NULL; + b = local->sta_bss_hash[STA_HASH(bss->bssid)]; + while (b) { + if (b == bss) { + if (!prev) + local->sta_bss_hash[STA_HASH(bss->bssid)] = + bss->hnext; + else + prev->hnext = bss->hnext; + break; + } + prev = b; + b = b->hnext; + } +} + +static struct ieee80211_sta_bss * +ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq, + u8 *ssid, u8 ssid_len) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_sta_bss *bss; + + bss = kzalloc(sizeof(*bss), GFP_ATOMIC); + if (!bss) + return NULL; + atomic_inc(&bss->users); + atomic_inc(&bss->users); + memcpy(bss->bssid, bssid, ETH_ALEN); + bss->freq = freq; + if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { + memcpy(bss->ssid, ssid, ssid_len); + bss->ssid_len = ssid_len; + } + + spin_lock_bh(&local->sta_bss_lock); + /* TODO: order by RSSI? */ + list_add_tail(&bss->list, &local->sta_bss_list); + __ieee80211_rx_bss_hash_add(local, bss); + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} + +#ifdef CONFIG_MAC80211_MESH +static struct ieee80211_sta_bss * +ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, + u8 *mesh_cfg, int freq) +{ + struct ieee80211_sta_bss *bss; + + spin_lock_bh(&local->sta_bss_lock); + bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; + while (bss) { + if (bss_mesh_cfg(bss) && + !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && + bss->freq == freq && + mesh_id_len == bss->mesh_id_len && + (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, + mesh_id_len))) { + atomic_inc(&bss->users); + break; + } + bss = bss->hnext; + } + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} + +static struct ieee80211_sta_bss * +ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, + u8 *mesh_cfg, int mesh_config_len, int freq) +{ + struct ieee80211_sta_bss *bss; + + if (mesh_config_len != MESH_CFG_LEN) + return NULL; + + bss = kzalloc(sizeof(*bss), GFP_ATOMIC); + if (!bss) + return NULL; + + bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); + if (!bss->mesh_cfg) { + kfree(bss); + return NULL; + } + + if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { + bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); + if (!bss->mesh_id) { + kfree(bss->mesh_cfg); + kfree(bss); + return NULL; + } + memcpy(bss->mesh_id, mesh_id, mesh_id_len); + } + + atomic_inc(&bss->users); + atomic_inc(&bss->users); + memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); + bss->mesh_id_len = mesh_id_len; + bss->freq = freq; + spin_lock_bh(&local->sta_bss_lock); + /* TODO: order by RSSI? */ + list_add_tail(&bss->list, &local->sta_bss_list); + __ieee80211_rx_bss_hash_add(local, bss); + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} +#endif + +static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) +{ + kfree(bss->ies); + kfree(bss_mesh_id(bss)); + kfree(bss_mesh_cfg(bss)); + kfree(bss); +} + static void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss); -static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta); -static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata); -static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *sdata, - u8 *ssid, size_t ssid_len); -static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta); -static void sta_rx_agg_session_timer_expired(unsigned long data); + struct ieee80211_sta_bss *bss) +{ + local_bh_disable(); + if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { + local_bh_enable(); + return; + } + + __ieee80211_rx_bss_hash_del(local, bss); + list_del(&bss->list); + spin_unlock_bh(&local->sta_bss_lock); + ieee80211_rx_bss_free(bss); +} +void ieee80211_rx_bss_list_init(struct ieee80211_local *local) +{ + spin_lock_init(&local->sta_bss_lock); + INIT_LIST_HEAD(&local->sta_bss_list); +} + +void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) +{ + struct ieee80211_sta_bss *bss, *tmp; -static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) + list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) + ieee80211_rx_bss_put(local, bss); +} + +static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) { u8 *end, *pos; @@ -111,13 +283,125 @@ static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) return NULL; } - +/* utils */ static int ecw2cw(int ecw) { return (1 << ecw) - 1; } +/* frame sending functions */ +void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + int encrypt) +{ + skb->dev = sdata->local->mdev; + skb_set_mac_header(skb, 0); + skb_set_network_header(skb, 0); + skb_set_transport_header(skb, 0); + skb->iif = sdata->dev->ifindex; + skb->do_not_encrypt = !encrypt; + + dev_queue_xmit(skb); +} + +static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta, + int transaction, u8 *extra, size_t extra_len, + int encrypt) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + 6 + extra_len); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for auth " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); + memset(mgmt, 0, 24 + 6); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_AUTH); + if (encrypt) + mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); + mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); + ifsta->auth_transaction = transaction + 1; + mgmt->u.auth.status_code = cpu_to_le16(0); + if (extra) + memcpy(skb_put(skb, extra_len), extra, extra_len); + + ieee80211_sta_tx(sdata, skb, encrypt); +} + +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, + u8 *ssid, size_t ssid_len) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u8 *pos, *supp_rates, *esupp_rates = NULL; + int i; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for probe " + "request\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_REQ); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + if (dst) { + memcpy(mgmt->da, dst, ETH_ALEN); + memcpy(mgmt->bssid, dst, ETH_ALEN); + } else { + memset(mgmt->da, 0xff, ETH_ALEN); + memset(mgmt->bssid, 0xff, ETH_ALEN); + } + pos = skb_put(skb, 2 + ssid_len); + *pos++ = WLAN_EID_SSID; + *pos++ = ssid_len; + memcpy(pos, ssid, ssid_len); + + supp_rates = skb_put(skb, 2); + supp_rates[0] = WLAN_EID_SUPP_RATES; + supp_rates[1] = 0; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + if (esupp_rates) { + pos = skb_put(skb, 1); + esupp_rates[1]++; + } else if (supp_rates[1] == 8) { + esupp_rates = skb_put(skb, 3); + esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; + esupp_rates[1] = 1; + pos = &esupp_rates[2]; + } else { + pos = skb_put(skb, 1); + supp_rates[1]++; + } + *pos = rate->bitrate / 5; + } + + ieee80211_sta_tx(sdata, skb, 0); +} + +/* MLME */ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss, int ibss) @@ -434,58 +718,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_sta_send_apinfo(sdata, ifsta); } -void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - int encrypt) -{ - skb->dev = sdata->local->mdev; - skb_set_mac_header(skb, 0); - skb_set_network_header(skb, 0); - skb_set_transport_header(skb, 0); - - skb->iif = sdata->dev->ifindex; - skb->do_not_encrypt = !encrypt; - - dev_queue_xmit(skb); -} - - -static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, - int transaction, u8 *extra, size_t extra_len, - int encrypt) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 6 + extra_len); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); - memset(mgmt, 0, 24 + 6); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_AUTH); - if (encrypt) - mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); - mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); - ifsta->auth_transaction = transaction + 1; - mgmt->u.auth.status_code = cpu_to_le16(0); - if (extra) - memcpy(skb_put(skb, extra_len), extra, extra_len); - - ieee80211_sta_tx(sdata, skb, encrypt); -} - static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -798,6 +1030,13 @@ static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tx(sdata, skb, 0); } +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) +{ + if (!sdata || !sdata->default_key || + sdata->default_key->conf.alg != ALG_WEP) + return 0; + return 1; +} static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) @@ -917,7 +1156,6 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, return 1; } - static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -999,82 +1237,12 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - if (disassoc) - ieee80211_set_disassoc(sdata, ifsta, true, true, - WLAN_REASON_PREV_AUTH_NOT_VALID); - else - mod_timer(&ifsta->timer, jiffies + - IEEE80211_MONITORING_INTERVAL); -} - - -static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_REQ); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (dst) { - memcpy(mgmt->da, dst, ETH_ALEN); - memcpy(mgmt->bssid, dst, ETH_ALEN); - } else { - memset(mgmt->da, 0xff, ETH_ALEN); - memset(mgmt->bssid, 0xff, ETH_ALEN); - } - pos = skb_put(skb, 2 + ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = ssid_len; - memcpy(pos, ssid, ssid_len); - - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - *pos = rate->bitrate / 5; - } - - ieee80211_sta_tx(sdata, skb, 0); -} - - -static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) -{ - if (!sdata || !sdata->default_key || - sdata->default_key->conf.alg != ALG_WEP) - return 0; - return 1; + if (disassoc) + ieee80211_set_disassoc(sdata, ifsta, true, true, + WLAN_REASON_PREV_AUTH_NOT_VALID); + else + mod_timer(&ifsta->timer, jiffies + + IEEE80211_MONITORING_INTERVAL); } @@ -1200,6 +1368,30 @@ void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 ieee80211_sta_tx(sdata, skb, 0); } +/* + * After accepting the AddBA Request we activated a timer, + * resetting it after each frame that arrives from the originator. + * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. + */ +static void sta_rx_agg_session_timer_expired(unsigned long data) +{ + /* not an elegant detour, but there is no choice as the timer passes + * only one argument, and various sta_info are needed here, so init + * flow in sta_info_create gives the TID as data, while the timer_to_id + * array gives the sta through container_of */ + u8 *ptid = (u8 *)data; + u8 *timer_to_id = ptid - *ptid; + struct sta_info *sta = container_of(timer_to_id, struct sta_info, + timer_to_tid[0]); + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); +#endif + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, + (u16)*ptid, WLAN_BACK_TIMER, + WLAN_REASON_QSTA_TIMEOUT); +} + static void ieee80211_sta_process_addba_request(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) @@ -1646,30 +1838,6 @@ timer_expired_exit: rcu_read_unlock(); } -/* - * After accepting the AddBA Request we activated a timer, - * resetting it after each frame that arrives from the originator. - * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. - */ -static void sta_rx_agg_session_timer_expired(unsigned long data) -{ - /* not an elegant detour, but there is no choice as the timer passes - * only one argument, and various sta_info are needed here, so init - * flow in sta_info_create gives the TID as data, while the timer_to_id - * array gives the sta through container_of */ - u8 *ptid = (u8 *)data; - u8 *timer_to_id = ptid - *ptid; - struct sta_info *sta = container_of(timer_to_id, struct sta_info, - timer_to_tid[0]); - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); -#endif - ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, - (u16)*ptid, WLAN_BACK_TIMER, - WLAN_REASON_QSTA_TIMEOUT); -} - void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) { struct ieee80211_local *local = sdata->local; @@ -1991,308 +2159,111 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); return; } - bss = ieee80211_rx_bss_get(local, ifsta->bssid, - local->hw.conf.channel->center_freq, - ifsta->ssid, ifsta->ssid_len); - if (bss) { - sta->last_signal = bss->signal; - sta->last_qual = bss->qual; - sta->last_noise = bss->noise; - ieee80211_rx_bss_put(local, bss); - } - - err = sta_info_insert(sta); - if (err) { - printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", sdata->dev->name, err); - rcu_read_unlock(); - return; - } - /* update new sta with its last rx activity */ - sta->last_rx = jiffies; - } - - /* - * FIXME: Do we really need to update the sta_info's information here? - * We already know about the AP (we found it in our list) so it - * should already be filled with the right info, no? - * As is stands, all this is racy because typically we assume - * the information that is filled in here (except flags) doesn't - * change while a STA structure is alive. As such, it should move - * to between the sta_info_alloc() and sta_info_insert() above. - */ - - set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | - WLAN_STA_AUTHORIZED); - - rates = 0; - basic_rates = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < elems.supp_rates_len; i++) { - int rate = (elems.supp_rates[i] & 0x7f) * 5; - - if (rate > 110) - have_higher_than_11mbit = true; - - for (j = 0; j < sband->n_bitrates; j++) { - if (sband->bitrates[j].bitrate == rate) - rates |= BIT(j); - if (elems.supp_rates[i] & 0x80) - basic_rates |= BIT(j); - } - } - - for (i = 0; i < elems.ext_supp_rates_len; i++) { - int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; - - if (rate > 110) - have_higher_than_11mbit = true; - - for (j = 0; j < sband->n_bitrates; j++) { - if (sband->bitrates[j].bitrate == rate) - rates |= BIT(j); - if (elems.ext_supp_rates[i] & 0x80) - basic_rates |= BIT(j); - } - } - - sta->supp_rates[local->hw.conf.channel->band] = rates; - sdata->basic_rates = basic_rates; - - /* cf. IEEE 802.11 9.2.12 */ - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && - have_higher_than_11mbit) - sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; - else - sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; - - if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && - (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { - struct ieee80211_ht_bss_info bss_info; - ieee80211_ht_cap_ie_to_ht_info( - (struct ieee80211_ht_cap *) - elems.ht_cap_elem, &sta->ht_info); - ieee80211_ht_addt_info_ie_to_ht_bss_info( - (struct ieee80211_ht_addt_info *) - elems.ht_info_elem, &bss_info); - ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info); - } - - rate_control_rate_init(sta, local); - - if (elems.wmm_param) { - set_sta_flags(sta, WLAN_STA_WME); - rcu_read_unlock(); - ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, - elems.wmm_param_len); - } else - rcu_read_unlock(); - - /* set AID and assoc capability, - * ieee80211_set_associated() will tell the driver */ - bss_conf->aid = aid; - bss_conf->assoc_capability = capab_info; - ieee80211_set_associated(sdata, ifsta); - - ieee80211_associated(sdata, ifsta); -} - - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) -{ - u8 hash_idx; - - if (bss_mesh_cfg(bss)) - hash_idx = mesh_id_hash(bss_mesh_id(bss), - bss_mesh_id_len(bss)); - else - hash_idx = STA_HASH(bss->bssid); - - bss->hnext = local->sta_bss_hash[hash_idx]; - local->sta_bss_hash[hash_idx] = bss; -} - - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_sta_bss *b, *prev = NULL; - b = local->sta_bss_hash[STA_HASH(bss->bssid)]; - while (b) { - if (b == bss) { - if (!prev) - local->sta_bss_hash[STA_HASH(bss->bssid)] = - bss->hnext; - else - prev->hnext = bss->hnext; - break; - } - prev = b; - b = b->hnext; - } -} - - -static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; - - bss = kzalloc(sizeof(*bss), GFP_ATOMIC); - if (!bss) - return NULL; - atomic_inc(&bss->users); - atomic_inc(&bss->users); - memcpy(bss->bssid, bssid, ETH_ALEN); - bss->freq = freq; - if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { - memcpy(bss->ssid, ssid, ssid_len); - bss->ssid_len = ssid_len; - } - - spin_lock_bh(&local->sta_bss_lock); - /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - -static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len) -{ - struct ieee80211_sta_bss *bss; - - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[STA_HASH(bssid)]; - while (bss) { - if (!bss_mesh_cfg(bss) && - !memcmp(bss->bssid, bssid, ETH_ALEN) && - bss->freq == freq && - bss->ssid_len == ssid_len && - (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { - atomic_inc(&bss->users); - break; - } - bss = bss->hnext; - } - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - -#ifdef CONFIG_MAC80211_MESH -static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, - u8 *mesh_cfg, int freq) -{ - struct ieee80211_sta_bss *bss; + bss = ieee80211_rx_bss_get(local, ifsta->bssid, + local->hw.conf.channel->center_freq, + ifsta->ssid, ifsta->ssid_len); + if (bss) { + sta->last_signal = bss->signal; + sta->last_qual = bss->qual; + sta->last_noise = bss->noise; + ieee80211_rx_bss_put(local, bss); + } - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; - while (bss) { - if (bss_mesh_cfg(bss) && - !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && - bss->freq == freq && - mesh_id_len == bss->mesh_id_len && - (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, - mesh_id_len))) { - atomic_inc(&bss->users); - break; + err = sta_info_insert(sta); + if (err) { + printk(KERN_DEBUG "%s: failed to insert STA entry for" + " the AP (error %d)\n", sdata->dev->name, err); + rcu_read_unlock(); + return; } - bss = bss->hnext; + /* update new sta with its last rx activity */ + sta->last_rx = jiffies; } - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} -static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, - u8 *mesh_cfg, int mesh_config_len, int freq) -{ - struct ieee80211_sta_bss *bss; + /* + * FIXME: Do we really need to update the sta_info's information here? + * We already know about the AP (we found it in our list) so it + * should already be filled with the right info, no? + * As is stands, all this is racy because typically we assume + * the information that is filled in here (except flags) doesn't + * change while a STA structure is alive. As such, it should move + * to between the sta_info_alloc() and sta_info_insert() above. + */ - if (mesh_config_len != MESH_CFG_LEN) - return NULL; + set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP | + WLAN_STA_AUTHORIZED); - bss = kzalloc(sizeof(*bss), GFP_ATOMIC); - if (!bss) - return NULL; + rates = 0; + basic_rates = 0; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); - if (!bss->mesh_cfg) { - kfree(bss); - return NULL; - } + for (i = 0; i < elems.supp_rates_len; i++) { + int rate = (elems.supp_rates[i] & 0x7f) * 5; - if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { - bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); - if (!bss->mesh_id) { - kfree(bss->mesh_cfg); - kfree(bss); - return NULL; + if (rate > 110) + have_higher_than_11mbit = true; + + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) + rates |= BIT(j); + if (elems.supp_rates[i] & 0x80) + basic_rates |= BIT(j); } - memcpy(bss->mesh_id, mesh_id, mesh_id_len); } - atomic_inc(&bss->users); - atomic_inc(&bss->users); - memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); - bss->mesh_id_len = mesh_id_len; - bss->freq = freq; - spin_lock_bh(&local->sta_bss_lock); - /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} -#endif - -static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) -{ - kfree(bss->ies); - kfree(bss_mesh_id(bss)); - kfree(bss_mesh_cfg(bss)); - kfree(bss); -} + for (i = 0; i < elems.ext_supp_rates_len; i++) { + int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; + if (rate > 110) + have_higher_than_11mbit = true; -static void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) -{ - local_bh_disable(); - if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { - local_bh_enable(); - return; + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) + rates |= BIT(j); + if (elems.ext_supp_rates[i] & 0x80) + basic_rates |= BIT(j); + } } - __ieee80211_rx_bss_hash_del(local, bss); - list_del(&bss->list); - spin_unlock_bh(&local->sta_bss_lock); - ieee80211_rx_bss_free(bss); -} + sta->supp_rates[local->hw.conf.channel->band] = rates; + sdata->basic_rates = basic_rates; + + /* cf. IEEE 802.11 9.2.12 */ + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && + have_higher_than_11mbit) + sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; + else + sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; + if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && + (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { + struct ieee80211_ht_bss_info bss_info; + ieee80211_ht_cap_ie_to_ht_info( + (struct ieee80211_ht_cap *) + elems.ht_cap_elem, &sta->ht_info); + ieee80211_ht_addt_info_ie_to_ht_bss_info( + (struct ieee80211_ht_addt_info *) + elems.ht_info_elem, &bss_info); + ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info); + } -void ieee80211_rx_bss_list_init(struct ieee80211_local *local) -{ - spin_lock_init(&local->sta_bss_lock); - INIT_LIST_HEAD(&local->sta_bss_list); -} + rate_control_rate_init(sta, local); + if (elems.wmm_param) { + set_sta_flags(sta, WLAN_STA_WME); + rcu_read_unlock(); + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, + elems.wmm_param_len); + } else + rcu_read_unlock(); -void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) -{ - struct ieee80211_sta_bss *bss, *tmp; + /* set AID and assoc capability, + * ieee80211_set_associated() will tell the driver */ + bss_conf->aid = aid; + bss_conf->assoc_capability = capab_info; + ieee80211_set_associated(sdata, ifsta); - list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) - ieee80211_rx_bss_put(local, bss); + ieee80211_associated(sdata, ifsta); } @@ -3145,104 +3116,15 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) void ieee80211_sta_timer(unsigned long data) { - struct ieee80211_sub_if_data *sdata = - (struct ieee80211_sub_if_data *) data; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = sdata->local; - - set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); - queue_work(local->hw.workqueue, &ifsta->work); -} - -void ieee80211_sta_work(struct work_struct *work) -{ - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, u.sta.work); - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_sta *ifsta; - struct sk_buff *skb; - - if (!netif_running(sdata->dev)) - return; - - if (local->sta_sw_scanning || local->sta_hw_scanning) - return; - - if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) - return; - ifsta = &sdata->u.sta; - - while ((skb = skb_dequeue(&ifsta->skb_queue))) - ieee80211_sta_rx_queued_mgmt(sdata, skb); - -#ifdef CONFIG_MAC80211_MESH - if (ifsta->preq_queue_len && - time_after(jiffies, - ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) - mesh_path_start_discovery(sdata); -#endif - - if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && - ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && - ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && - test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { - if (ifsta->scan_ssid_len) - ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); - else - ieee80211_sta_start_scan(sdata, NULL, 0); - return; - } - - if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { - if (ieee80211_sta_config_auth(sdata, ifsta)) - return; - clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); - } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) - return; - - switch (ifsta->state) { - case IEEE80211_STA_MLME_DISABLED: - break; - case IEEE80211_STA_MLME_DIRECT_PROBE: - ieee80211_direct_probe(sdata, ifsta); - break; - case IEEE80211_STA_MLME_AUTHENTICATE: - ieee80211_authenticate(sdata, ifsta); - break; - case IEEE80211_STA_MLME_ASSOCIATE: - ieee80211_associate(sdata, ifsta); - break; - case IEEE80211_STA_MLME_ASSOCIATED: - ieee80211_associated(sdata, ifsta); - break; - case IEEE80211_STA_MLME_IBSS_SEARCH: - ieee80211_sta_find_ibss(sdata, ifsta); - break; - case IEEE80211_STA_MLME_IBSS_JOINED: - ieee80211_sta_merge_ibss(sdata, ifsta); - break; -#ifdef CONFIG_MAC80211_MESH - case IEEE80211_STA_MLME_MESH_UP: - ieee80211_mesh_housekeeping(sdata, ifsta); - break; -#endif - default: - WARN_ON(1); - break; - } - - if (ieee80211_privacy_mismatch(sdata, ifsta)) { - printk(KERN_DEBUG "%s: privacy configuration mismatch and " - "mixed-cell disabled - disassociate\n", sdata->dev->name); + struct ieee80211_sub_if_data *sdata = + (struct ieee80211_sub_if_data *) data; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_local *local = sdata->local; - ieee80211_set_disassoc(sdata, ifsta, false, true, - WLAN_REASON_UNSPECIFIED); - } + set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); + queue_work(local->hw.workqueue, &ifsta->work); } - static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -3327,85 +3209,6 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, return 0; } -static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss, *selected = NULL; - int top_rssi = 0, freq; - - spin_lock_bh(&local->sta_bss_lock); - freq = local->oper_channel->center_freq; - list_for_each_entry(bss, &local->sta_bss_list, list) { - if (!(bss->capability & WLAN_CAPABILITY_ESS)) - continue; - - if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | - IEEE80211_STA_AUTO_BSSID_SEL | - IEEE80211_STA_AUTO_CHANNEL_SEL)) && - (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ - !!sdata->default_key)) - continue; - - if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && - bss->freq != freq) - continue; - - if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && - memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) - continue; - - if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && - !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) - continue; - - if (!selected || top_rssi < bss->signal) { - selected = bss; - top_rssi = bss->signal; - } - } - if (selected) - atomic_inc(&selected->users); - spin_unlock_bh(&local->sta_bss_lock); - - if (selected) { - ieee80211_set_freq(sdata, selected->freq); - if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) - ieee80211_sta_set_ssid(sdata, selected->ssid, - selected->ssid_len); - ieee80211_sta_set_bssid(sdata, selected->bssid); - ieee80211_sta_def_wmm_params(sdata, selected, 0); - - /* Send out direct probe if no probe resp was received or - * the one we have is outdated - */ - if (!selected->last_probe_resp || - time_after(jiffies, selected->last_probe_resp - + IEEE80211_SCAN_RESULT_EXPIRE)) - ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; - else - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; - - ieee80211_rx_bss_put(local, selected); - ieee80211_sta_reset_auth(sdata, ifsta); - return 0; - } else { - if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { - ifsta->assoc_scan_tries++; - if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(sdata, NULL, 0); - else - ieee80211_sta_start_scan(sdata, ifsta->ssid, - ifsta->ssid_len); - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; - set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); - } else - ifsta->state = IEEE80211_STA_MLME_DISABLED; - } - return -1; -} - - static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -4273,6 +4076,85 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, } +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_sta_bss *bss, *selected = NULL; + int top_rssi = 0, freq; + + spin_lock_bh(&local->sta_bss_lock); + freq = local->oper_channel->center_freq; + list_for_each_entry(bss, &local->sta_bss_list, list) { + if (!(bss->capability & WLAN_CAPABILITY_ESS)) + continue; + + if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | + IEEE80211_STA_AUTO_BSSID_SEL | + IEEE80211_STA_AUTO_CHANNEL_SEL)) && + (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ + !!sdata->default_key)) + continue; + + if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && + bss->freq != freq) + continue; + + if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && + memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) + continue; + + if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && + !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) + continue; + + if (!selected || top_rssi < bss->signal) { + selected = bss; + top_rssi = bss->signal; + } + } + if (selected) + atomic_inc(&selected->users); + spin_unlock_bh(&local->sta_bss_lock); + + if (selected) { + ieee80211_set_freq(sdata, selected->freq); + if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) + ieee80211_sta_set_ssid(sdata, selected->ssid, + selected->ssid_len); + ieee80211_sta_set_bssid(sdata, selected->bssid); + ieee80211_sta_def_wmm_params(sdata, selected, 0); + + /* Send out direct probe if no probe resp was received or + * the one we have is outdated + */ + if (!selected->last_probe_resp || + time_after(jiffies, selected->last_probe_resp + + IEEE80211_SCAN_RESULT_EXPIRE)) + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + else + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + + ieee80211_rx_bss_put(local, selected); + ieee80211_sta_reset_auth(sdata, ifsta); + return 0; + } else { + if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { + ifsta->assoc_scan_tries++; + if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) + ieee80211_sta_start_scan(sdata, NULL, 0); + else + ieee80211_sta_start_scan(sdata, ifsta->ssid, + ifsta->ssid_len); + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); + } else + ifsta->state = IEEE80211_STA_MLME_DISABLED; + } + return -1; +} + + int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; @@ -4326,3 +4208,91 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, } } EXPORT_SYMBOL(ieee80211_notify_mac); + +void ieee80211_sta_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, u.sta.work); + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_sta *ifsta; + struct sk_buff *skb; + + if (!netif_running(sdata->dev)) + return; + + if (local->sta_sw_scanning || local->sta_hw_scanning) + return; + + if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && + sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) + return; + ifsta = &sdata->u.sta; + + while ((skb = skb_dequeue(&ifsta->skb_queue))) + ieee80211_sta_rx_queued_mgmt(sdata, skb); + +#ifdef CONFIG_MAC80211_MESH + if (ifsta->preq_queue_len && + time_after(jiffies, + ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) + mesh_path_start_discovery(sdata); +#endif + + if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && + ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && + ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && + test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { + if (ifsta->scan_ssid_len) + ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); + else + ieee80211_sta_start_scan(sdata, NULL, 0); + return; + } + + if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { + if (ieee80211_sta_config_auth(sdata, ifsta)) + return; + clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); + } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) + return; + + switch (ifsta->state) { + case IEEE80211_STA_MLME_DISABLED: + break; + case IEEE80211_STA_MLME_DIRECT_PROBE: + ieee80211_direct_probe(sdata, ifsta); + break; + case IEEE80211_STA_MLME_AUTHENTICATE: + ieee80211_authenticate(sdata, ifsta); + break; + case IEEE80211_STA_MLME_ASSOCIATE: + ieee80211_associate(sdata, ifsta); + break; + case IEEE80211_STA_MLME_ASSOCIATED: + ieee80211_associated(sdata, ifsta); + break; + case IEEE80211_STA_MLME_IBSS_SEARCH: + ieee80211_sta_find_ibss(sdata, ifsta); + break; + case IEEE80211_STA_MLME_IBSS_JOINED: + ieee80211_sta_merge_ibss(sdata, ifsta); + break; +#ifdef CONFIG_MAC80211_MESH + case IEEE80211_STA_MLME_MESH_UP: + ieee80211_mesh_housekeeping(sdata, ifsta); + break; +#endif + default: + WARN_ON(1); + break; + } + + if (ieee80211_privacy_mismatch(sdata, ifsta)) { + printk(KERN_DEBUG "%s: privacy configuration mismatch and " + "mixed-cell disabled - disassociate\n", sdata->dev->name); + + ieee80211_set_disassoc(sdata, ifsta, false, true, + WLAN_REASON_UNSPECIFIED); + } +} -- cgit v1.2.3 From 491775a50787b9fbb09b5735be3d111c65935f5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:23 +0200 Subject: mac80211: use sdata pointer for scan interface Since we now use sdata pointers most of the time, using a netdev pointer here is somewhat artificial, use an sdata pointer instead. Replace a netdev-prefix in a few messages by a wiphy-prefix. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/main.c | 2 +- net/mac80211/mlme.c | 24 +++++++++++------------- 3 files changed, 13 insertions(+), 15 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c68d4df11196..a33bbd1ca2b1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -636,7 +636,7 @@ struct ieee80211_local { enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; unsigned long last_scan_completed; struct delayed_work scan_work; - struct net_device *scan_dev; + struct ieee80211_sub_if_data *scan_sdata; struct ieee80211_channel *oper_channel, *scan_channel; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7dc063197259..6df4a2e15098 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -551,7 +551,7 @@ static int ieee80211_stop(struct net_device *dev) synchronize_rcu(); skb_queue_purge(&sdata->u.sta.skb_queue); - if (local->scan_dev == sdata->dev) { + if (local->scan_sdata == sdata) { if (!local->ops->hw_scan) { local->sta_sw_scanning = 0; cancel_delayed_work(&local->scan_work); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 67c38235a3c5..f60212b75005 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3507,19 +3507,18 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) void ieee80211_scan_completed(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); - struct net_device *dev = local->scan_dev; struct ieee80211_sub_if_data *sdata; union iwreq_data wrqu; local->last_scan_completed = jiffies; memset(&wrqu, 0, sizeof(wrqu)); - wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); + wireless_send_event(local->scan_sdata->dev, SIOCGIWSCAN, &wrqu, NULL); if (local->sta_hw_scanning) { local->sta_hw_scanning = 0; if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " - "channel after scan\n", dev->name); + "channel after scan\n", wiphy_name(local->hw.wiphy)); /* Restart STA timer for HW scan case */ rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) @@ -3532,7 +3531,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) local->sta_sw_scanning = 0; if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " - "channel after scan\n", dev->name); + "channel after scan\n", wiphy_name(local->hw.wiphy)); netif_tx_lock_bh(local->mdev); @@ -3562,8 +3561,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) } rcu_read_unlock(); -done: - sdata = IEEE80211_DEV_TO_SUB_IF(dev); + done: + sdata = local->scan_sdata; if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || @@ -3578,8 +3577,7 @@ void ieee80211_sta_scan_work(struct work_struct *work) { struct ieee80211_local *local = container_of(work, struct ieee80211_local, scan_work.work); - struct net_device *dev = local->scan_dev; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_sub_if_data *sdata = local->scan_sdata; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; int skip; @@ -3627,7 +3625,7 @@ void ieee80211_sta_scan_work(struct work_struct *work) local->scan_channel = chan; if (ieee80211_hw_config(local)) { printk(KERN_DEBUG "%s: failed to set freq to " - "%d MHz for scan\n", dev->name, + "%d MHz for scan\n", wiphy_name(local->hw.wiphy), chan->center_freq); skip = 1; } @@ -3697,7 +3695,7 @@ static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, */ if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == scan_sdata->dev) + if (local->scan_sdata == scan_sdata) return 0; return -EBUSY; } @@ -3707,7 +3705,7 @@ static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, ssid, ssid_len); if (!rc) { local->sta_hw_scanning = 1; - local->scan_dev = scan_sdata->dev; + local->scan_sdata = scan_sdata; } return rc; } @@ -3734,7 +3732,7 @@ static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, local->scan_state = SCAN_SET_CHANNEL; local->scan_channel_idx = 0; local->scan_band = IEEE80211_BAND_2GHZ; - local->scan_dev = scan_sdata->dev; + local->scan_sdata = scan_sdata; netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; @@ -3762,7 +3760,7 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t return ieee80211_sta_start_scan(sdata, ssid, ssid_len); if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == sdata->dev) + if (local->scan_sdata == sdata) return 0; return -EBUSY; } -- cgit v1.2.3 From ee96d6ef82cc29421569b7cb7f7c7ee90168ec50 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:24 +0200 Subject: mac80211: remove useless non-NULL tests from scan results code I'm surprised nobody complained about these before. What a waste. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f60212b75005..ba502ce132d9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3822,6 +3822,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, char *current_ev, char *end_buf) { struct iw_event iwe; + char *buf; if (time_after(jiffies, bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) @@ -3896,7 +3897,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); - if (bss && bss->supp_rates_len > 0) { + if (bss->supp_rates_len > 0) { /* display all supported rates in readable format */ char *p = current_ev + iwe_stream_lcp_len(info); int i; @@ -3915,30 +3916,25 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, current_ev = p; } - if (bss) { - char *buf; - buf = kmalloc(30, GFP_ATOMIC); - if (buf) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, - &iwe, buf); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, " Last beacon: %dms ago", - jiffies_to_msecs(jiffies - bss->last_update)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, buf); - kfree(buf); - } + buf = kmalloc(30, GFP_ATOMIC); + if (buf) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, buf); + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, " Last beacon: %dms ago", + jiffies_to_msecs(jiffies - bss->last_update)); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, &iwe, buf); + kfree(buf); } if (bss_mesh_cfg(bss)) { - char *buf; u8 *cfg = bss_mesh_cfg(bss); buf = kmalloc(50, GFP_ATOMIC); if (buf) { -- cgit v1.2.3 From 0a51b27e956bd9580296c48191b78175ed8b5971 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:25 +0200 Subject: mac80211: start moving scan code from mlme Here's a first patch to move some code from mlme.c to a new file called scan.c. The end result will hopefully be a more manageable mlme.c. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Makefile | 1 + net/mac80211/ieee80211_i.h | 13 +- net/mac80211/mlme.c | 559 ++------------------------------------------- net/mac80211/scan.c | 553 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 582 insertions(+), 544 deletions(-) create mode 100644 net/mac80211/scan.c (limited to 'net/mac80211') diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index a169b0201d61..376280a420ac 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -7,6 +7,7 @@ mac80211-y := \ sta_info.o \ wep.o \ wpa.o \ + scan.o \ mlme.o \ iface.o \ rate.o \ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a33bbd1ca2b1..25dccd5cb2ff 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -53,6 +53,12 @@ struct ieee80211_local; * increased memory use (about 2 kB of RAM per entry). */ #define IEEE80211_FRAGMENT_MAX 4 +/* + * Time after which we ignore scan results and no longer report/use + * them in any way. + */ +#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) + struct ieee80211_fragment_entry { unsigned long first_frag_time; unsigned int seq; @@ -924,8 +930,13 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, enum ieee80211_band band); void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); +void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, + u8 *ssid, size_t ssid_len); void ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems); + struct ieee802_11_elems *elems); +void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); +int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, + u8 *ssid, size_t ssid_len); #ifdef CONFIG_MAC80211_MESH void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ba502ce132d9..2caea9759b7e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -46,10 +46,6 @@ #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) -#define IEEE80211_PROBE_DELAY (HZ / 33) -#define IEEE80211_CHANNEL_TIME (HZ / 33) -#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) -#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) @@ -341,8 +337,8 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tx(sdata, skb, encrypt); } -static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, - u8 *ssid, size_t ssid_len) +void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, + u8 *ssid, size_t ssid_len) { struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; @@ -3466,543 +3462,6 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) } -static void ieee80211_send_nullfunc(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - int powersave) -{ - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; - __le16 fc; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " - "frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(nullfunc, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - if (powersave) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - nullfunc->frame_control = fc; - memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); - memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); - memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); - - ieee80211_sta_tx(sdata, skb, 0); -} - - -static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) -{ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_sta_timer((unsigned long)sdata); -} - -void ieee80211_scan_completed(struct ieee80211_hw *hw) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; - union iwreq_data wrqu; - - local->last_scan_completed = jiffies; - memset(&wrqu, 0, sizeof(wrqu)); - wireless_send_event(local->scan_sdata->dev, SIOCGIWSCAN, &wrqu, NULL); - - if (local->sta_hw_scanning) { - local->sta_hw_scanning = 0; - if (ieee80211_hw_config(local)) - printk(KERN_DEBUG "%s: failed to restore operational " - "channel after scan\n", wiphy_name(local->hw.wiphy)); - /* Restart STA timer for HW scan case */ - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) - ieee80211_restart_sta_timer(sdata); - rcu_read_unlock(); - - goto done; - } - - local->sta_sw_scanning = 0; - if (ieee80211_hw_config(local)) - printk(KERN_DEBUG "%s: failed to restore operational " - "channel after scan\n", wiphy_name(local->hw.wiphy)); - - - netif_tx_lock_bh(local->mdev); - netif_addr_lock(local->mdev); - local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); - - netif_addr_unlock(local->mdev); - netif_tx_unlock_bh(local->mdev); - - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { - /* Tell AP we're back */ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { - if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { - ieee80211_send_nullfunc(local, sdata, 0); - netif_tx_wake_all_queues(sdata->dev); - } - } else - netif_tx_wake_all_queues(sdata->dev); - - ieee80211_restart_sta_timer(sdata); - } - rcu_read_unlock(); - - done: - sdata = local->scan_sdata; - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && - !ieee80211_sta_active_ibss(sdata))) - ieee80211_sta_find_ibss(sdata, ifsta); - } -} -EXPORT_SYMBOL(ieee80211_scan_completed); - -void ieee80211_sta_scan_work(struct work_struct *work) -{ - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, scan_work.work); - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *chan; - int skip; - unsigned long next_delay = 0; - - if (!local->sta_sw_scanning) - return; - - switch (local->scan_state) { - case SCAN_SET_CHANNEL: - /* - * Get current scan band. scan_band may be IEEE80211_NUM_BANDS - * after we successfully scanned the last channel of the last - * band (and the last band is supported by the hw) - */ - if (local->scan_band < IEEE80211_NUM_BANDS) - sband = local->hw.wiphy->bands[local->scan_band]; - else - sband = NULL; - - /* - * If we are at an unsupported band and have more bands - * left to scan, advance to the next supported one. - */ - while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { - local->scan_band++; - sband = local->hw.wiphy->bands[local->scan_band]; - local->scan_channel_idx = 0; - } - - /* if no more bands/channels left, complete scan */ - if (!sband || local->scan_channel_idx >= sband->n_channels) { - ieee80211_scan_completed(local_to_hw(local)); - return; - } - skip = 0; - chan = &sband->channels[local->scan_channel_idx]; - - if (chan->flags & IEEE80211_CHAN_DISABLED || - (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && - chan->flags & IEEE80211_CHAN_NO_IBSS)) - skip = 1; - - if (!skip) { - local->scan_channel = chan; - if (ieee80211_hw_config(local)) { - printk(KERN_DEBUG "%s: failed to set freq to " - "%d MHz for scan\n", wiphy_name(local->hw.wiphy), - chan->center_freq); - skip = 1; - } - } - - /* advance state machine to next channel/band */ - local->scan_channel_idx++; - if (local->scan_channel_idx >= sband->n_channels) { - /* - * scan_band may end up == IEEE80211_NUM_BANDS, but - * we'll catch that case above and complete the scan - * if that is the case. - */ - local->scan_band++; - local->scan_channel_idx = 0; - } - - if (skip) - break; - - next_delay = IEEE80211_PROBE_DELAY + - usecs_to_jiffies(local->hw.channel_change_time); - local->scan_state = SCAN_SEND_PROBE; - break; - case SCAN_SEND_PROBE: - next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; - local->scan_state = SCAN_SET_CHANNEL; - - if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) - break; - ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, - local->scan_ssid_len); - next_delay = IEEE80211_CHANNEL_TIME; - break; - } - - if (local->sta_sw_scanning) - queue_delayed_work(local->hw.workqueue, &local->scan_work, - next_delay); -} - - -static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, - u8 *ssid, size_t ssid_len) -{ - struct ieee80211_local *local = scan_sdata->local; - struct ieee80211_sub_if_data *sdata; - - if (ssid_len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - - /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) - * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS - * BSSID: MACAddress - * SSID - * ScanType: ACTIVE, PASSIVE - * ProbeDelay: delay (in microseconds) to be used prior to transmitting - * a Probe frame during active scanning - * ChannelList - * MinChannelTime (>= ProbeDelay), in TU - * MaxChannelTime: (>= MinChannelTime), in TU - */ - - /* MLME-SCAN.confirm - * BSSDescriptionSet - * ResultCode: SUCCESS, INVALID_PARAMETERS - */ - - if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_sdata == scan_sdata) - return 0; - return -EBUSY; - } - - if (local->ops->hw_scan) { - int rc = local->ops->hw_scan(local_to_hw(local), - ssid, ssid_len); - if (!rc) { - local->sta_hw_scanning = 1; - local->scan_sdata = scan_sdata; - } - return rc; - } - - local->sta_sw_scanning = 1; - - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { - if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { - netif_tx_stop_all_queues(sdata->dev); - ieee80211_send_nullfunc(local, sdata, 1); - } - } else - netif_tx_stop_all_queues(sdata->dev); - } - rcu_read_unlock(); - - if (ssid) { - local->scan_ssid_len = ssid_len; - memcpy(local->scan_ssid, ssid, ssid_len); - } else - local->scan_ssid_len = 0; - local->scan_state = SCAN_SET_CHANNEL; - local->scan_channel_idx = 0; - local->scan_band = IEEE80211_BAND_2GHZ; - local->scan_sdata = scan_sdata; - - netif_addr_lock_bh(local->mdev); - local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; - local->ops->configure_filter(local_to_hw(local), - FIF_BCN_PRBRESP_PROMISC, - &local->filter_flags, - local->mdev->mc_count, - local->mdev->mc_list); - netif_addr_unlock_bh(local->mdev); - - /* TODO: start scan as soon as all nullfunc frames are ACKed */ - queue_delayed_work(local->hw.workqueue, &local->scan_work, - IEEE80211_CHANNEL_TIME); - - return 0; -} - - -int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) -{ - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = sdata->local; - - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return ieee80211_sta_start_scan(sdata, ssid, ssid_len); - - if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_sdata == sdata) - return 0; - return -EBUSY; - } - - ifsta->scan_ssid_len = ssid_len; - if (ssid_len) - memcpy(ifsta->scan_ssid, ssid, ssid_len); - set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); - queue_work(local->hw.workqueue, &ifsta->work); - return 0; -} - - -static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, - struct ieee80211_sta_bss *bss, - char **current_ev, char *end_buf) -{ - u8 *pos, *end, *next; - struct iw_event iwe; - - if (bss == NULL || bss->ies == NULL) - return; - - /* - * If needed, fragment the IEs buffer (at IE boundaries) into short - * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. - */ - pos = bss->ies; - end = pos + bss->ies_len; - - while (end - pos > IW_GENERIC_IE_MAX) { - next = pos + 2 + pos[1]; - while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) - next = next + 2 + next[1]; - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = next - pos; - *current_ev = iwe_stream_add_point(info, *current_ev, - end_buf, &iwe, pos); - - pos = next; - } - - if (end > pos) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = end - pos; - *current_ev = iwe_stream_add_point(info, *current_ev, - end_buf, &iwe, pos); - } -} - - -static char * -ieee80211_sta_scan_result(struct ieee80211_local *local, - struct iw_request_info *info, - struct ieee80211_sta_bss *bss, - char *current_ev, char *end_buf) -{ - struct iw_event iwe; - char *buf; - - if (time_after(jiffies, - bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) - return current_ev; - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_ADDR_LEN); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - if (bss_mesh_cfg(bss)) { - iwe.u.data.length = bss_mesh_id_len(bss); - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss_mesh_id(bss)); - } else { - iwe.u.data.length = bss->ssid_len; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid); - } - - if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) - || bss_mesh_cfg(bss)) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - if (bss_mesh_cfg(bss)) - iwe.u.mode = IW_MODE_MESH; - else if (bss->capability & WLAN_CAPABILITY_ESS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); - } - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); - iwe.u.freq.e = 0; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = bss->freq; - iwe.u.freq.e = 6; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = bss->qual; - iwe.u.qual.level = bss->signal; - iwe.u.qual.noise = bss->noise; - iwe.u.qual.updated = local->wstats_flags; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_QUAL_LEN); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (bss->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, ""); - - ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); - - if (bss->supp_rates_len > 0) { - /* display all supported rates in readable format */ - char *p = current_ev + iwe_stream_lcp_len(info); - int i; - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - - for (i = 0; i < bss->supp_rates_len; i++) { - iwe.u.bitrate.value = ((bss->supp_rates[i] & - 0x7f) * 500000); - p = iwe_stream_add_value(info, current_ev, p, - end_buf, &iwe, IW_EV_PARAM_LEN); - } - current_ev = p; - } - - buf = kmalloc(30, GFP_ATOMIC); - if (buf) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, " Last beacon: %dms ago", - jiffies_to_msecs(jiffies - bss->last_update)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, buf); - kfree(buf); - } - - if (bss_mesh_cfg(bss)) { - u8 *cfg = bss_mesh_cfg(bss); - buf = kmalloc(50, GFP_ATOMIC); - if (buf) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "Mesh network (version %d)", cfg[0]); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, - &iwe, buf); - sprintf(buf, "Path Selection Protocol ID: " - "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], - cfg[4]); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, - &iwe, buf); - sprintf(buf, "Path Selection Metric ID: " - "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], - cfg[8]); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, - &iwe, buf); - sprintf(buf, "Congestion Control Mode ID: " - "0x%02X%02X%02X%02X", cfg[9], cfg[10], - cfg[11], cfg[12]); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, - &iwe, buf); - sprintf(buf, "Channel Precedence: " - "0x%02X%02X%02X%02X", cfg[13], cfg[14], - cfg[15], cfg[16]); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, - &iwe, buf); - kfree(buf); - } - } - - return current_ev; -} - - -int ieee80211_sta_scan_results(struct ieee80211_local *local, - struct iw_request_info *info, - char *buf, size_t len) -{ - char *current_ev = buf; - char *end_buf = buf + len; - struct ieee80211_sta_bss *bss; - - spin_lock_bh(&local->sta_bss_lock); - list_for_each_entry(bss, &local->sta_bss_list, list) { - if (buf + len - current_ev <= IW_EV_ADDR_LEN) { - spin_unlock_bh(&local->sta_bss_lock); - return -E2BIG; - } - current_ev = ieee80211_sta_scan_result(local, info, bss, - current_ev, end_buf); - } - spin_unlock_bh(&local->sta_bss_lock); - return current_ev - buf; -} - - int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; @@ -4290,3 +3749,17 @@ void ieee80211_sta_work(struct work_struct *work) WLAN_REASON_UNSPECIFIED); } } + +void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata = local->scan_sdata; + struct ieee80211_if_sta *ifsta; + + if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + ifsta = &sdata->u.sta; + if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || + (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && + !ieee80211_sta_active_ibss(sdata))) + ieee80211_sta_find_ibss(sdata, ifsta); + } +} diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c new file mode 100644 index 000000000000..68fa782acd75 --- /dev/null +++ b/net/mac80211/scan.c @@ -0,0 +1,553 @@ +/* + * BSS client mode implementation + * Copyright 2003, Jouni Malinen + * Copyright 2004, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * Copyright 2006-2007 Jiri Benc + * Copyright 2007, Michael Wu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "ieee80211_i.h" + +#define IEEE80211_PROBE_DELAY (HZ / 33) +#define IEEE80211_CHANNEL_TIME (HZ / 33) +#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) + + +static void ieee80211_send_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + int powersave) +{ + struct sk_buff *skb; + struct ieee80211_hdr *nullfunc; + __le16 fc; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); + memset(nullfunc, 0, 24); + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS); + if (powersave) + fc |= cpu_to_le16(IEEE80211_FCTL_PM); + nullfunc->frame_control = fc; + memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); + memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); + memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); + + ieee80211_sta_tx(sdata, skb, 0); +} + +static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) +{ + if (sdata->vif.type == IEEE80211_IF_TYPE_STA || + ieee80211_vif_is_mesh(&sdata->vif)) + ieee80211_sta_timer((unsigned long)sdata); +} + +void ieee80211_scan_completed(struct ieee80211_hw *hw) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + union iwreq_data wrqu; + + local->last_scan_completed = jiffies; + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(local->scan_sdata->dev, SIOCGIWSCAN, &wrqu, NULL); + + if (local->sta_hw_scanning) { + local->sta_hw_scanning = 0; + if (ieee80211_hw_config(local)) + printk(KERN_DEBUG "%s: failed to restore operational " + "channel after scan\n", wiphy_name(local->hw.wiphy)); + /* Restart STA timer for HW scan case */ + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + ieee80211_restart_sta_timer(sdata); + rcu_read_unlock(); + + goto done; + } + + local->sta_sw_scanning = 0; + if (ieee80211_hw_config(local)) + printk(KERN_DEBUG "%s: failed to restore operational " + "channel after scan\n", wiphy_name(local->hw.wiphy)); + + + netif_tx_lock_bh(local->mdev); + netif_addr_lock(local->mdev); + local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; + local->ops->configure_filter(local_to_hw(local), + FIF_BCN_PRBRESP_PROMISC, + &local->filter_flags, + local->mdev->mc_count, + local->mdev->mc_list); + + netif_addr_unlock(local->mdev); + netif_tx_unlock_bh(local->mdev); + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + /* Tell AP we're back */ + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { + ieee80211_send_nullfunc(local, sdata, 0); + netif_tx_wake_all_queues(sdata->dev); + } + } else + netif_tx_wake_all_queues(sdata->dev); + + ieee80211_restart_sta_timer(sdata); + } + rcu_read_unlock(); + + done: + ieee80211_mlme_notify_scan_completed(local); +} +EXPORT_SYMBOL(ieee80211_scan_completed); + + +void ieee80211_sta_scan_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, scan_work.work); + struct ieee80211_sub_if_data *sdata = local->scan_sdata; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *chan; + int skip; + unsigned long next_delay = 0; + + if (!local->sta_sw_scanning) + return; + + switch (local->scan_state) { + case SCAN_SET_CHANNEL: + /* + * Get current scan band. scan_band may be IEEE80211_NUM_BANDS + * after we successfully scanned the last channel of the last + * band (and the last band is supported by the hw) + */ + if (local->scan_band < IEEE80211_NUM_BANDS) + sband = local->hw.wiphy->bands[local->scan_band]; + else + sband = NULL; + + /* + * If we are at an unsupported band and have more bands + * left to scan, advance to the next supported one. + */ + while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { + local->scan_band++; + sband = local->hw.wiphy->bands[local->scan_band]; + local->scan_channel_idx = 0; + } + + /* if no more bands/channels left, complete scan */ + if (!sband || local->scan_channel_idx >= sband->n_channels) { + ieee80211_scan_completed(local_to_hw(local)); + return; + } + skip = 0; + chan = &sband->channels[local->scan_channel_idx]; + + if (chan->flags & IEEE80211_CHAN_DISABLED || + (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + chan->flags & IEEE80211_CHAN_NO_IBSS)) + skip = 1; + + if (!skip) { + local->scan_channel = chan; + if (ieee80211_hw_config(local)) { + printk(KERN_DEBUG "%s: failed to set freq to " + "%d MHz for scan\n", wiphy_name(local->hw.wiphy), + chan->center_freq); + skip = 1; + } + } + + /* advance state machine to next channel/band */ + local->scan_channel_idx++; + if (local->scan_channel_idx >= sband->n_channels) { + /* + * scan_band may end up == IEEE80211_NUM_BANDS, but + * we'll catch that case above and complete the scan + * if that is the case. + */ + local->scan_band++; + local->scan_channel_idx = 0; + } + + if (skip) + break; + + next_delay = IEEE80211_PROBE_DELAY + + usecs_to_jiffies(local->hw.channel_change_time); + local->scan_state = SCAN_SEND_PROBE; + break; + case SCAN_SEND_PROBE: + next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; + local->scan_state = SCAN_SET_CHANNEL; + + if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) + break; + ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, + local->scan_ssid_len); + next_delay = IEEE80211_CHANNEL_TIME; + break; + } + + if (local->sta_sw_scanning) + queue_delayed_work(local->hw.workqueue, &local->scan_work, + next_delay); +} + + +int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, + u8 *ssid, size_t ssid_len) +{ + struct ieee80211_local *local = scan_sdata->local; + struct ieee80211_sub_if_data *sdata; + + if (ssid_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + + /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) + * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS + * BSSID: MACAddress + * SSID + * ScanType: ACTIVE, PASSIVE + * ProbeDelay: delay (in microseconds) to be used prior to transmitting + * a Probe frame during active scanning + * ChannelList + * MinChannelTime (>= ProbeDelay), in TU + * MaxChannelTime: (>= MinChannelTime), in TU + */ + + /* MLME-SCAN.confirm + * BSSDescriptionSet + * ResultCode: SUCCESS, INVALID_PARAMETERS + */ + + if (local->sta_sw_scanning || local->sta_hw_scanning) { + if (local->scan_sdata == scan_sdata) + return 0; + return -EBUSY; + } + + if (local->ops->hw_scan) { + int rc = local->ops->hw_scan(local_to_hw(local), + ssid, ssid_len); + if (!rc) { + local->sta_hw_scanning = 1; + local->scan_sdata = scan_sdata; + } + return rc; + } + + local->sta_sw_scanning = 1; + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { + netif_tx_stop_all_queues(sdata->dev); + ieee80211_send_nullfunc(local, sdata, 1); + } + } else + netif_tx_stop_all_queues(sdata->dev); + } + rcu_read_unlock(); + + if (ssid) { + local->scan_ssid_len = ssid_len; + memcpy(local->scan_ssid, ssid, ssid_len); + } else + local->scan_ssid_len = 0; + local->scan_state = SCAN_SET_CHANNEL; + local->scan_channel_idx = 0; + local->scan_band = IEEE80211_BAND_2GHZ; + local->scan_sdata = scan_sdata; + + netif_addr_lock_bh(local->mdev); + local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; + local->ops->configure_filter(local_to_hw(local), + FIF_BCN_PRBRESP_PROMISC, + &local->filter_flags, + local->mdev->mc_count, + local->mdev->mc_list); + netif_addr_unlock_bh(local->mdev); + + /* TODO: start scan as soon as all nullfunc frames are ACKed */ + queue_delayed_work(local->hw.workqueue, &local->scan_work, + IEEE80211_CHANNEL_TIME); + + return 0; +} + + +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) +{ + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_local *local = sdata->local; + + if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + return ieee80211_sta_start_scan(sdata, ssid, ssid_len); + + if (local->sta_sw_scanning || local->sta_hw_scanning) { + if (local->scan_sdata == sdata) + return 0; + return -EBUSY; + } + + ifsta->scan_ssid_len = ssid_len; + if (ssid_len) + memcpy(ifsta->scan_ssid, ssid, ssid_len); + set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); + queue_work(local->hw.workqueue, &ifsta->work); + return 0; +} + + +static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, + struct ieee80211_sta_bss *bss, + char **current_ev, char *end_buf) +{ + u8 *pos, *end, *next; + struct iw_event iwe; + + if (bss == NULL || bss->ies == NULL) + return; + + /* + * If needed, fragment the IEs buffer (at IE boundaries) into short + * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. + */ + pos = bss->ies; + end = pos + bss->ies_len; + + while (end - pos > IW_GENERIC_IE_MAX) { + next = pos + 2 + pos[1]; + while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) + next = next + 2 + next[1]; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = next - pos; + *current_ev = iwe_stream_add_point(info, *current_ev, + end_buf, &iwe, pos); + + pos = next; + } + + if (end > pos) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = end - pos; + *current_ev = iwe_stream_add_point(info, *current_ev, + end_buf, &iwe, pos); + } +} + + +static char * +ieee80211_sta_scan_result(struct ieee80211_local *local, + struct iw_request_info *info, + struct ieee80211_sta_bss *bss, + char *current_ev, char *end_buf) +{ + struct iw_event iwe; + char *buf; + + if (time_after(jiffies, + bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) + return current_ev; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_ADDR_LEN); + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + if (bss_mesh_cfg(bss)) { + iwe.u.data.length = bss_mesh_id_len(bss); + iwe.u.data.flags = 1; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, bss_mesh_id(bss)); + } else { + iwe.u.data.length = bss->ssid_len; + iwe.u.data.flags = 1; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, bss->ssid); + } + + if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) + || bss_mesh_cfg(bss)) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (bss_mesh_cfg(bss)) + iwe.u.mode = IW_MODE_MESH; + else if (bss->capability & WLAN_CAPABILITY_ESS) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, + &iwe, IW_EV_UINT_LEN); + } + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); + iwe.u.freq.e = 0; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_FREQ_LEN); + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = bss->freq; + iwe.u.freq.e = 6; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_FREQ_LEN); + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = bss->qual; + iwe.u.qual.level = bss->signal; + iwe.u.qual.noise = bss->noise; + iwe.u.qual.updated = local->wstats_flags; + current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + IW_EV_QUAL_LEN); + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (bss->capability & WLAN_CAPABILITY_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, ""); + + ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); + + if (bss->supp_rates_len > 0) { + /* display all supported rates in readable format */ + char *p = current_ev + iwe_stream_lcp_len(info); + int i; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + + for (i = 0; i < bss->supp_rates_len; i++) { + iwe.u.bitrate.value = ((bss->supp_rates[i] & + 0x7f) * 500000); + p = iwe_stream_add_value(info, current_ev, p, + end_buf, &iwe, IW_EV_PARAM_LEN); + } + current_ev = p; + } + + buf = kmalloc(30, GFP_ATOMIC); + if (buf) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, end_buf, + &iwe, buf); + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, " Last beacon: %dms ago", + jiffies_to_msecs(jiffies - bss->last_update)); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, &iwe, buf); + kfree(buf); + } + + if (bss_mesh_cfg(bss)) { + u8 *cfg = bss_mesh_cfg(bss); + buf = kmalloc(50, GFP_ATOMIC); + if (buf) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "Mesh network (version %d)", cfg[0]); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, + &iwe, buf); + sprintf(buf, "Path Selection Protocol ID: " + "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], + cfg[4]); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, + &iwe, buf); + sprintf(buf, "Path Selection Metric ID: " + "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], + cfg[8]); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, + &iwe, buf); + sprintf(buf, "Congestion Control Mode ID: " + "0x%02X%02X%02X%02X", cfg[9], cfg[10], + cfg[11], cfg[12]); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, + &iwe, buf); + sprintf(buf, "Channel Precedence: " + "0x%02X%02X%02X%02X", cfg[13], cfg[14], + cfg[15], cfg[16]); + iwe.u.data.length = strlen(buf); + current_ev = iwe_stream_add_point(info, current_ev, + end_buf, + &iwe, buf); + kfree(buf); + } + } + + return current_ev; +} + + +int ieee80211_sta_scan_results(struct ieee80211_local *local, + struct iw_request_info *info, + char *buf, size_t len) +{ + char *current_ev = buf; + char *end_buf = buf + len; + struct ieee80211_sta_bss *bss; + + spin_lock_bh(&local->sta_bss_lock); + list_for_each_entry(bss, &local->sta_bss_list, list) { + if (buf + len - current_ev <= IW_EV_ADDR_LEN) { + spin_unlock_bh(&local->sta_bss_lock); + return -E2BIG; + } + current_ev = ieee80211_sta_scan_result(local, info, bss, + current_ev, end_buf); + } + spin_unlock_bh(&local->sta_bss_lock); + return current_ev - buf; +} -- cgit v1.2.3 From 98c8fccfaea838e62ffde2f2e44568844e0e5472 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:26 +0200 Subject: mac80211: refactor and move scan RX code This patch refactors some code and moves the scan RX function to scan.c. More importantly, however, it changes it so that the MLME's beacon/probe_resp functions aren't invoked when scanning so that we can remove a "if (scanning)" conditions from two places. There's a very slight behavioural change in this patch: now, when scanning, IBSS and mesh aren't updated even on the same channel. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 9 ++ net/mac80211/mlme.c | 253 +++++++++++++++++++++------------------------ net/mac80211/scan.c | 68 ++++++++++++ 3 files changed, 194 insertions(+), 136 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 25dccd5cb2ff..4753ed3f3f10 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -937,6 +937,15 @@ void ieee802_11_parse_elems(u8 *start, size_t len, void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, u8 *ssid, size_t ssid_len); +struct ieee80211_sta_bss * +ieee80211_bss_info_update(struct ieee80211_local *local, + struct ieee80211_rx_status *rx_status, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee802_11_elems *elems, + int freq, bool beacon); +void ieee80211_rx_bss_put(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss); #ifdef CONFIG_MAC80211_MESH void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2caea9759b7e..1708a3d1cd38 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -128,10 +128,9 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, } static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq, +ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); @@ -230,8 +229,8 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) kfree(bss); } -static void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) +void ieee80211_rx_bss_put(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss) { local_bh_disable(); if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { @@ -2443,74 +2442,16 @@ static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, return mandatory_rates; } -static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status, - struct ieee802_11_elems *elems) +struct ieee80211_sta_bss * +ieee80211_bss_info_update(struct ieee80211_local *local, + struct ieee80211_rx_status *rx_status, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee802_11_elems *elems, + int freq, bool beacon) { - struct ieee80211_local *local = sdata->local; - int freq, clen; struct ieee80211_sta_bss *bss; - struct sta_info *sta; - struct ieee80211_channel *channel; - u64 beacon_timestamp, rx_timestamp; - u64 supp_rates = 0; - bool beacon = ieee80211_is_beacon(mgmt->frame_control); - enum ieee80211_band band = rx_status->band; - DECLARE_MAC_BUF(mac); - DECLARE_MAC_BUF(mac2); - - if (elems->ds_params && elems->ds_params_len == 1) - freq = ieee80211_channel_to_frequency(elems->ds_params[0]); - else - freq = rx_status->freq; - - channel = ieee80211_get_channel(local->hw.wiphy, freq); - - if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) - return; - - if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && - elems->mesh_config && mesh_matches_local(elems, sdata)) { - supp_rates = ieee80211_sta_get_rates(local, elems, band); - - mesh_neighbour_update(mgmt->sa, supp_rates, sdata, - mesh_peer_accepts_plinks(elems)); - } - - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && - memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { - supp_rates = ieee80211_sta_get_rates(local, elems, band); - - rcu_read_lock(); - - sta = sta_info_get(local, mgmt->sa); - if (sta) { - u64 prev_rates; - - prev_rates = sta->supp_rates[band]; - /* make sure mandatory rates are always added */ - sta->supp_rates[band] = supp_rates | - ieee80211_sta_get_mandatory_rates(local, band); - -#ifdef CONFIG_MAC80211_IBSS_DEBUG - if (sta->supp_rates[band] != prev_rates) - printk(KERN_DEBUG "%s: updated supp_rates set " - "for %s based on beacon info (0x%llx | " - "0x%llx -> 0x%llx)\n", - sdata->dev->name, print_mac(mac, sta->addr), - (unsigned long long) prev_rates, - (unsigned long long) supp_rates, - (unsigned long long) sta->supp_rates[band]); -#endif - } else { - ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, - mgmt->sa, supp_rates); - } - - rcu_read_unlock(); - } + int clen; #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) @@ -2528,10 +2469,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, elems->mesh_config_len, freq); else #endif - bss = ieee80211_rx_bss_add(sdata, mgmt->bssid, freq, + bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) - return; + return NULL; } else { #if 0 /* TODO: order by RSSI? */ @@ -2578,17 +2519,114 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bss->supp_rates_len += clen; } - bss->band = band; + bss->band = rx_status->band; - beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); - - bss->timestamp = beacon_timestamp; + bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); bss->last_update = jiffies; bss->signal = rx_status->signal; bss->noise = rx_status->noise; bss->qual = rx_status->qual; + bss->wmm_used = elems->wmm_param || elems->wmm_info; + if (!beacon) bss->last_probe_resp = jiffies; + + /* + * For probe responses, or if we don't have any information yet, + * use the IEs from the beacon. + */ + if (!bss->ies || !beacon) { + if (bss->ies == NULL || bss->ies_len < elems->total_len) { + kfree(bss->ies); + bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); + } + if (bss->ies) { + memcpy(bss->ies, elems->ie_start, elems->total_len); + bss->ies_len = elems->total_len; + } else + bss->ies_len = 0; + } + + return bss; +} + +static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee80211_rx_status *rx_status, + struct ieee802_11_elems *elems, + bool beacon) +{ + struct ieee80211_local *local = sdata->local; + int freq; + struct ieee80211_sta_bss *bss; + struct sta_info *sta; + struct ieee80211_channel *channel; + u64 beacon_timestamp, rx_timestamp; + u64 supp_rates = 0; + enum ieee80211_band band = rx_status->band; + DECLARE_MAC_BUF(mac); + DECLARE_MAC_BUF(mac2); + + if (elems->ds_params && elems->ds_params_len == 1) + freq = ieee80211_channel_to_frequency(elems->ds_params[0]); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(local->hw.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) + return; + + if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && + elems->mesh_config && mesh_matches_local(elems, sdata)) { + supp_rates = ieee80211_sta_get_rates(local, elems, band); + + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, + mesh_peer_accepts_plinks(elems)); + } + + if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && + memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { + supp_rates = ieee80211_sta_get_rates(local, elems, band); + + rcu_read_lock(); + + sta = sta_info_get(local, mgmt->sa); + if (sta) { + u64 prev_rates; + + prev_rates = sta->supp_rates[band]; + /* make sure mandatory rates are always added */ + sta->supp_rates[band] = supp_rates | + ieee80211_sta_get_mandatory_rates(local, band); + +#ifdef CONFIG_MAC80211_IBSS_DEBUG + if (sta->supp_rates[band] != prev_rates) + printk(KERN_DEBUG "%s: updated supp_rates set " + "for %s based on beacon info (0x%llx | " + "0x%llx -> 0x%llx)\n", + sdata->dev->name, print_mac(mac, sta->addr), + (unsigned long long) prev_rates, + (unsigned long long) supp_rates, + (unsigned long long) sta->supp_rates[band]); +#endif + } else { + ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, + mgmt->sa, supp_rates); + } + + rcu_read_unlock(); + } + + bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, + freq, beacon); + if (!bss) + return; + + /* was just updated in ieee80211_bss_info_update */ + beacon_timestamp = bss->timestamp; + /* * In STA mode, the remaining parameters should not be overridden * by beacons because they're not necessarily accurate there. @@ -2599,21 +2637,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, return; } - if (bss->ies == NULL || bss->ies_len < elems->total_len) { - kfree(bss->ies); - bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); - } - if (bss->ies) { - memcpy(bss->ies, elems->ie_start, elems->total_len); - bss->ies_len = elems->total_len; - } else - bss->ies_len = 0; - - bss->wmm_used = elems->wmm_param || elems->wmm_info; - /* check if we need to merge IBSS */ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && - !local->sta_sw_scanning && !local->sta_hw_scanning && bss->capability & WLAN_CAPABILITY_IBSS && bss->freq == local->oper_channel->center_freq && elems->ssid_len == sdata->u.sta.ssid_len && @@ -2690,7 +2715,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); /* direct probe may be part of the association flow */ if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, @@ -2721,7 +2746,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; @@ -2731,15 +2756,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - /* Do not send changes to driver if we are scanning. This removes - * requirement that a driver's bss_info_changed/conf_tx functions - * need to be atomic. - * This is really ugly code, we should rewrite scanning and make - * all this more understandable for humans. - */ - if (local->sta_sw_scanning || local->sta_hw_scanning) - return; - ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); @@ -2982,41 +2998,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, } -ieee80211_rx_result -ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_mgmt *mgmt; - __le16 fc; - - if (skb->len < 2) - return RX_DROP_UNUSABLE; - - mgmt = (struct ieee80211_mgmt *) skb->data; - fc = mgmt->frame_control; - - if (ieee80211_is_ctl(fc)) - return RX_CONTINUE; - - if (skb->len < 24) - return RX_DROP_MONITOR; - - if (ieee80211_is_probe_resp(fc)) { - ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); - dev_kfree_skb(skb); - return RX_QUEUED; - } - - if (ieee80211_is_beacon(fc)) { - ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); - dev_kfree_skb(skb); - return RX_QUEUED; - } - - return RX_CONTINUE; -} - - static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -3233,7 +3214,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", sdata->dev->name, print_mac(mac, bssid)); - bss = ieee80211_rx_bss_add(sdata, bssid, + bss = ieee80211_rx_bss_add(local, bssid, local->hw.conf.channel->center_freq, sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 68fa782acd75..2848ba3a08e3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -23,6 +23,74 @@ #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) +ieee80211_rx_result +ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_mgmt *mgmt; + struct ieee80211_sta_bss *bss; + u8 *elements; + struct ieee80211_channel *channel; + size_t baselen; + int freq; + __le16 fc; + bool presp, beacon = false; + struct ieee802_11_elems elems; + + if (skb->len < 2) + return RX_DROP_UNUSABLE; + + mgmt = (struct ieee80211_mgmt *) skb->data; + fc = mgmt->frame_control; + + if (ieee80211_is_ctl(fc)) + return RX_CONTINUE; + + if (skb->len < 24) + return RX_DROP_MONITOR; + + presp = ieee80211_is_probe_resp(fc); + if (presp) { + /* ignore ProbeResp to foreign address */ + if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + return RX_DROP_MONITOR; + + presp = true; + elements = mgmt->u.probe_resp.variable; + baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + } else { + beacon = ieee80211_is_beacon(fc); + baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); + elements = mgmt->u.beacon.variable; + } + + if (!presp && !beacon) + return RX_CONTINUE; + + if (baselen > skb->len) + return RX_DROP_MONITOR; + + ieee802_11_parse_elems(elements, skb->len - baselen, &elems); + + if (elems.ds_params && elems.ds_params_len == 1) + freq = ieee80211_channel_to_frequency(elems.ds_params[0]); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) + return RX_DROP_MONITOR; + + bss = ieee80211_bss_info_update(sdata->local, rx_status, + mgmt, skb->len, &elems, + freq, beacon); + ieee80211_rx_bss_put(sdata->local, bss); + + dev_kfree_skb(skb); + return RX_QUEUED; +} + static void ieee80211_send_nullfunc(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, int powersave) -- cgit v1.2.3 From 5484e23749e78d5a4f56928efaf3c4b0d862b7a6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:27 +0200 Subject: mac80211: move BSS handling to scan code This moves all the BSS list handling out of mlme.c to scan.c, no further changes except fixing kzalloc/atomic_inc/atomic_inc to kzalloc/atomic_set(2). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 6 + net/mac80211/mlme.c | 310 +-------------------------------------------- net/mac80211/scan.c | 305 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 313 insertions(+), 308 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4753ed3f3f10..792c09ca08e3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -944,6 +944,12 @@ ieee80211_bss_info_update(struct ieee80211_local *local, size_t len, struct ieee802_11_elems *elems, int freq, bool beacon); +struct ieee80211_sta_bss * +ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, + u8 *ssid, u8 ssid_len); +struct ieee80211_sta_bss * +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, + u8 *ssid, u8 ssid_len); void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_sta_bss *bss); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1708a3d1cd38..be3292bfabe3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -11,11 +11,6 @@ * published by the Free Software Foundation. */ -/* TODO: - * order BSS list by RSSI(?) ("quality of AP") - * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, - * SSID) - */ #include #include #include @@ -67,195 +62,10 @@ #define IEEE80211_MIN_AMPDU_BUF 0x8 #define IEEE80211_MAX_AMPDU_BUF 0x40 -/* BSS handling */ -static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len) -{ - struct ieee80211_sta_bss *bss; - - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[STA_HASH(bssid)]; - while (bss) { - if (!bss_mesh_cfg(bss) && - !memcmp(bss->bssid, bssid, ETH_ALEN) && - bss->freq == freq && - bss->ssid_len == ssid_len && - (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { - atomic_inc(&bss->users); - break; - } - bss = bss->hnext; - } - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) -{ - u8 hash_idx; - - if (bss_mesh_cfg(bss)) - hash_idx = mesh_id_hash(bss_mesh_id(bss), - bss_mesh_id_len(bss)); - else - hash_idx = STA_HASH(bss->bssid); - - bss->hnext = local->sta_bss_hash[hash_idx]; - local->sta_bss_hash[hash_idx] = bss; -} - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_sta_bss *b, *prev = NULL; - b = local->sta_bss_hash[STA_HASH(bss->bssid)]; - while (b) { - if (b == bss) { - if (!prev) - local->sta_bss_hash[STA_HASH(bss->bssid)] = - bss->hnext; - else - prev->hnext = bss->hnext; - break; - } - prev = b; - b = b->hnext; - } -} - -static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len) -{ - struct ieee80211_sta_bss *bss; - - bss = kzalloc(sizeof(*bss), GFP_ATOMIC); - if (!bss) - return NULL; - atomic_inc(&bss->users); - atomic_inc(&bss->users); - memcpy(bss->bssid, bssid, ETH_ALEN); - bss->freq = freq; - if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { - memcpy(bss->ssid, ssid, ssid_len); - bss->ssid_len = ssid_len; - } - - spin_lock_bh(&local->sta_bss_lock); - /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - -#ifdef CONFIG_MAC80211_MESH -static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, - u8 *mesh_cfg, int freq) -{ - struct ieee80211_sta_bss *bss; - - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; - while (bss) { - if (bss_mesh_cfg(bss) && - !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && - bss->freq == freq && - mesh_id_len == bss->mesh_id_len && - (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, - mesh_id_len))) { - atomic_inc(&bss->users); - break; - } - bss = bss->hnext; - } - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} - -static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, - u8 *mesh_cfg, int mesh_config_len, int freq) -{ - struct ieee80211_sta_bss *bss; - - if (mesh_config_len != MESH_CFG_LEN) - return NULL; - - bss = kzalloc(sizeof(*bss), GFP_ATOMIC); - if (!bss) - return NULL; - - bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); - if (!bss->mesh_cfg) { - kfree(bss); - return NULL; - } - - if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { - bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); - if (!bss->mesh_id) { - kfree(bss->mesh_cfg); - kfree(bss); - return NULL; - } - memcpy(bss->mesh_id, mesh_id, mesh_id_len); - } - - atomic_inc(&bss->users); - atomic_inc(&bss->users); - memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); - bss->mesh_id_len = mesh_id_len; - bss->freq = freq; - spin_lock_bh(&local->sta_bss_lock); - /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); - return bss; -} -#endif - -static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) -{ - kfree(bss->ies); - kfree(bss_mesh_id(bss)); - kfree(bss_mesh_cfg(bss)); - kfree(bss); -} - -void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) -{ - local_bh_disable(); - if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { - local_bh_enable(); - return; - } - - __ieee80211_rx_bss_hash_del(local, bss); - list_del(&bss->list); - spin_unlock_bh(&local->sta_bss_lock); - ieee80211_rx_bss_free(bss); -} - -void ieee80211_rx_bss_list_init(struct ieee80211_local *local) -{ - spin_lock_init(&local->sta_bss_lock); - INIT_LIST_HEAD(&local->sta_bss_list); -} - -void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) +/* utils */ +static int ecw2cw(int ecw) { - struct ieee80211_sta_bss *bss, *tmp; - - list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) - ieee80211_rx_bss_put(local, bss); + return (1 << ecw) - 1; } static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) @@ -278,12 +88,6 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) return NULL; } -/* utils */ -static int ecw2cw(int ecw) -{ - return (1 << ecw) - 1; -} - /* frame sending functions */ void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt) @@ -2442,114 +2246,6 @@ static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, return mandatory_rates; } -struct ieee80211_sta_bss * -ieee80211_bss_info_update(struct ieee80211_local *local, - struct ieee80211_rx_status *rx_status, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee802_11_elems *elems, - int freq, bool beacon) -{ - struct ieee80211_sta_bss *bss; - int clen; - -#ifdef CONFIG_MAC80211_MESH - if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, - elems->mesh_id_len, elems->mesh_config, freq); - else -#endif - bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, - elems->ssid, elems->ssid_len); - if (!bss) { -#ifdef CONFIG_MAC80211_MESH - if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, - elems->mesh_id_len, elems->mesh_config, - elems->mesh_config_len, freq); - else -#endif - bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, - elems->ssid, elems->ssid_len); - if (!bss) - return NULL; - } else { -#if 0 - /* TODO: order by RSSI? */ - spin_lock_bh(&local->sta_bss_lock); - list_move_tail(&bss->list, &local->sta_bss_list); - spin_unlock_bh(&local->sta_bss_lock); -#endif - } - - /* save the ERP value so that it is available at association time */ - if (elems->erp_info && elems->erp_info_len >= 1) { - bss->erp_value = elems->erp_info[0]; - bss->has_erp_value = 1; - } - - bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); - bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); - - if (elems->tim) { - struct ieee80211_tim_ie *tim_ie = - (struct ieee80211_tim_ie *)elems->tim; - bss->dtim_period = tim_ie->dtim_period; - } - - /* set default value for buggy APs */ - if (!elems->tim || bss->dtim_period == 0) - bss->dtim_period = 1; - - bss->supp_rates_len = 0; - if (elems->supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; - if (clen > elems->supp_rates_len) - clen = elems->supp_rates_len; - memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, - clen); - bss->supp_rates_len += clen; - } - if (elems->ext_supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; - if (clen > elems->ext_supp_rates_len) - clen = elems->ext_supp_rates_len; - memcpy(&bss->supp_rates[bss->supp_rates_len], - elems->ext_supp_rates, clen); - bss->supp_rates_len += clen; - } - - bss->band = rx_status->band; - - bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); - bss->last_update = jiffies; - bss->signal = rx_status->signal; - bss->noise = rx_status->noise; - bss->qual = rx_status->qual; - bss->wmm_used = elems->wmm_param || elems->wmm_info; - - if (!beacon) - bss->last_probe_resp = jiffies; - - /* - * For probe responses, or if we don't have any information yet, - * use the IEs from the beacon. - */ - if (!bss->ies || !beacon) { - if (bss->ies == NULL || bss->ies_len < elems->total_len) { - kfree(bss->ies); - bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); - } - if (bss->ies) { - memcpy(bss->ies, elems->ie_start, elems->total_len); - bss->ies_len = elems->total_len; - } else - bss->ies_len = 0; - } - - return bss; -} - static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 2848ba3a08e3..1beefb5ad6fb 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -1,5 +1,6 @@ /* - * BSS client mode implementation + * Scanning implementation + * * Copyright 2003, Jouni Malinen * Copyright 2004, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. @@ -11,17 +12,319 @@ * published by the Free Software Foundation. */ +/* TODO: + * order BSS list by RSSI(?) ("quality of AP") + * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, + * SSID) + */ + #include #include #include #include #include "ieee80211_i.h" +#include "mesh.h" #define IEEE80211_PROBE_DELAY (HZ / 33) #define IEEE80211_CHANNEL_TIME (HZ / 33) #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) +void ieee80211_rx_bss_list_init(struct ieee80211_local *local) +{ + spin_lock_init(&local->sta_bss_lock); + INIT_LIST_HEAD(&local->sta_bss_list); +} + +void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) +{ + struct ieee80211_sta_bss *bss, *tmp; + + list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) + ieee80211_rx_bss_put(local, bss); +} + +struct ieee80211_sta_bss * +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, + u8 *ssid, u8 ssid_len) +{ + struct ieee80211_sta_bss *bss; + + spin_lock_bh(&local->sta_bss_lock); + bss = local->sta_bss_hash[STA_HASH(bssid)]; + while (bss) { + if (!bss_mesh_cfg(bss) && + !memcmp(bss->bssid, bssid, ETH_ALEN) && + bss->freq == freq && + bss->ssid_len == ssid_len && + (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { + atomic_inc(&bss->users); + break; + } + bss = bss->hnext; + } + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} + +/* Caller must hold local->sta_bss_lock */ +static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss) +{ + u8 hash_idx; + + if (bss_mesh_cfg(bss)) + hash_idx = mesh_id_hash(bss_mesh_id(bss), + bss_mesh_id_len(bss)); + else + hash_idx = STA_HASH(bss->bssid); + + bss->hnext = local->sta_bss_hash[hash_idx]; + local->sta_bss_hash[hash_idx] = bss; +} + +/* Caller must hold local->sta_bss_lock */ +static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss) +{ + struct ieee80211_sta_bss *b, *prev = NULL; + b = local->sta_bss_hash[STA_HASH(bss->bssid)]; + while (b) { + if (b == bss) { + if (!prev) + local->sta_bss_hash[STA_HASH(bss->bssid)] = + bss->hnext; + else + prev->hnext = bss->hnext; + break; + } + prev = b; + b = b->hnext; + } +} + +struct ieee80211_sta_bss * +ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, + u8 *ssid, u8 ssid_len) +{ + struct ieee80211_sta_bss *bss; + + bss = kzalloc(sizeof(*bss), GFP_ATOMIC); + if (!bss) + return NULL; + atomic_set(&bss->users, 2); + memcpy(bss->bssid, bssid, ETH_ALEN); + bss->freq = freq; + if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { + memcpy(bss->ssid, ssid, ssid_len); + bss->ssid_len = ssid_len; + } + + spin_lock_bh(&local->sta_bss_lock); + /* TODO: order by RSSI? */ + list_add_tail(&bss->list, &local->sta_bss_list); + __ieee80211_rx_bss_hash_add(local, bss); + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} + +#ifdef CONFIG_MAC80211_MESH +static struct ieee80211_sta_bss * +ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, + u8 *mesh_cfg, int freq) +{ + struct ieee80211_sta_bss *bss; + + spin_lock_bh(&local->sta_bss_lock); + bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; + while (bss) { + if (bss_mesh_cfg(bss) && + !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && + bss->freq == freq && + mesh_id_len == bss->mesh_id_len && + (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, + mesh_id_len))) { + atomic_inc(&bss->users); + break; + } + bss = bss->hnext; + } + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} + +static struct ieee80211_sta_bss * +ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, + u8 *mesh_cfg, int mesh_config_len, int freq) +{ + struct ieee80211_sta_bss *bss; + + if (mesh_config_len != MESH_CFG_LEN) + return NULL; + + bss = kzalloc(sizeof(*bss), GFP_ATOMIC); + if (!bss) + return NULL; + + bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); + if (!bss->mesh_cfg) { + kfree(bss); + return NULL; + } + + if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { + bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); + if (!bss->mesh_id) { + kfree(bss->mesh_cfg); + kfree(bss); + return NULL; + } + memcpy(bss->mesh_id, mesh_id, mesh_id_len); + } + + atomic_set(&bss->users, 2); + memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); + bss->mesh_id_len = mesh_id_len; + bss->freq = freq; + spin_lock_bh(&local->sta_bss_lock); + /* TODO: order by RSSI? */ + list_add_tail(&bss->list, &local->sta_bss_list); + __ieee80211_rx_bss_hash_add(local, bss); + spin_unlock_bh(&local->sta_bss_lock); + return bss; +} +#endif + +static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) +{ + kfree(bss->ies); + kfree(bss_mesh_id(bss)); + kfree(bss_mesh_cfg(bss)); + kfree(bss); +} + +void ieee80211_rx_bss_put(struct ieee80211_local *local, + struct ieee80211_sta_bss *bss) +{ + local_bh_disable(); + if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { + local_bh_enable(); + return; + } + + __ieee80211_rx_bss_hash_del(local, bss); + list_del(&bss->list); + spin_unlock_bh(&local->sta_bss_lock); + ieee80211_rx_bss_free(bss); +} + +struct ieee80211_sta_bss * +ieee80211_bss_info_update(struct ieee80211_local *local, + struct ieee80211_rx_status *rx_status, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee802_11_elems *elems, + int freq, bool beacon) +{ + struct ieee80211_sta_bss *bss; + int clen; + +#ifdef CONFIG_MAC80211_MESH + if (elems->mesh_config) + bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, + elems->mesh_id_len, elems->mesh_config, freq); + else +#endif + bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, + elems->ssid, elems->ssid_len); + if (!bss) { +#ifdef CONFIG_MAC80211_MESH + if (elems->mesh_config) + bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, + elems->mesh_id_len, elems->mesh_config, + elems->mesh_config_len, freq); + else +#endif + bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, + elems->ssid, elems->ssid_len); + if (!bss) + return NULL; + } else { +#if 0 + /* TODO: order by RSSI? */ + spin_lock_bh(&local->sta_bss_lock); + list_move_tail(&bss->list, &local->sta_bss_list); + spin_unlock_bh(&local->sta_bss_lock); +#endif + } + + /* save the ERP value so that it is available at association time */ + if (elems->erp_info && elems->erp_info_len >= 1) { + bss->erp_value = elems->erp_info[0]; + bss->has_erp_value = 1; + } + + bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); + bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); + + if (elems->tim) { + struct ieee80211_tim_ie *tim_ie = + (struct ieee80211_tim_ie *)elems->tim; + bss->dtim_period = tim_ie->dtim_period; + } + + /* set default value for buggy APs */ + if (!elems->tim || bss->dtim_period == 0) + bss->dtim_period = 1; + + bss->supp_rates_len = 0; + if (elems->supp_rates) { + clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; + if (clen > elems->supp_rates_len) + clen = elems->supp_rates_len; + memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, + clen); + bss->supp_rates_len += clen; + } + if (elems->ext_supp_rates) { + clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; + if (clen > elems->ext_supp_rates_len) + clen = elems->ext_supp_rates_len; + memcpy(&bss->supp_rates[bss->supp_rates_len], + elems->ext_supp_rates, clen); + bss->supp_rates_len += clen; + } + + bss->band = rx_status->band; + + bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); + bss->last_update = jiffies; + bss->signal = rx_status->signal; + bss->noise = rx_status->noise; + bss->qual = rx_status->qual; + bss->wmm_used = elems->wmm_param || elems->wmm_info; + + if (!beacon) + bss->last_probe_resp = jiffies; + + /* + * For probe responses, or if we don't have any information yet, + * use the IEs from the beacon. + */ + if (!bss->ies || !beacon) { + if (bss->ies == NULL || bss->ies_len < elems->total_len) { + kfree(bss->ies); + bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); + } + if (bss->ies) { + memcpy(bss->ies, elems->ie_start, elems->total_len); + bss->ies_len = elems->total_len; + } else + bss->ies_len = 0; + } + + return bss; +} ieee80211_rx_result ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, -- cgit v1.2.3 From 44d414dbff9d5bf46fc09f2e68567b5848cbbfd3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:28 +0200 Subject: mac80211: move some HT code out of mlme.c Some of the HT code in mlme.c is misplaced: * constants/definitions belong to the ieee80211.h header * code being used in other modes as well shouldn't be there Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 18 +++ net/mac80211/Makefile | 1 + net/mac80211/ht.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/mlme.c | 321 --------------------------------------------- 4 files changed, 347 insertions(+), 321 deletions(-) create mode 100644 net/mac80211/ht.c (limited to 'net/mac80211') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 333d3ae76883..abc1abc63bf0 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -643,6 +643,9 @@ struct ieee80211_mgmt { } u; } __attribute__ ((packed)); +/* mgmt header + 1 byte category code */ +#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u) + /* Control frames */ struct ieee80211_rts { @@ -737,6 +740,21 @@ struct ieee80211_ht_addt_info { #define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004 #define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010 +/* block-ack parameters */ +#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 +#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C +#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 +#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 +#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 + +/* + * A-PMDU buffer sizes + * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) + */ +#define IEEE80211_MIN_AMPDU_BUF 0x8 +#define IEEE80211_MAX_AMPDU_BUF 0x40 + + /* Spatial Multiplexing Power Save Modes */ #define WLAN_HT_CAP_SM_PS_STATIC 0 #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 376280a420ac..1a7ac50910c3 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -8,6 +8,7 @@ mac80211-y := \ wep.o \ wpa.o \ scan.o \ + ht.o \ mlme.o \ iface.o \ rate.o \ diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c new file mode 100644 index 000000000000..5ccf1bc17466 --- /dev/null +++ b/net/mac80211/ht.c @@ -0,0 +1,328 @@ +/* + * HT handling + * + * Copyright 2003, Jouni Malinen + * Copyright 2004, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * Copyright 2006-2007 Jiri Benc + * Copyright 2007, Michael Wu + * Copyright 2007-2008, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include "ieee80211_i.h" +#include "sta_info.h" + +int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, + struct ieee80211_ht_info *ht_info) +{ + + if (ht_info == NULL) + return -EINVAL; + + memset(ht_info, 0, sizeof(*ht_info)); + + if (ht_cap_ie) { + u8 ampdu_info = ht_cap_ie->ampdu_params_info; + + ht_info->ht_supported = 1; + ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); + ht_info->ampdu_factor = + ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; + ht_info->ampdu_density = + (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; + memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); + } else + ht_info->ht_supported = 0; + + return 0; +} + +int ieee80211_ht_addt_info_ie_to_ht_bss_info( + struct ieee80211_ht_addt_info *ht_add_info_ie, + struct ieee80211_ht_bss_info *bss_info) +{ + if (bss_info == NULL) + return -EINVAL; + + memset(bss_info, 0, sizeof(*bss_info)); + + if (ht_add_info_ie) { + u16 op_mode; + op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); + + bss_info->primary_channel = ht_add_info_ie->control_chan; + bss_info->bss_cap = ht_add_info_ie->ht_param; + bss_info->bss_op_mode = (u8)(op_mode & 0xff); + } + + return 0; +} + +void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, + u16 tid, u8 dialog_token, u16 start_seq_num, + u16 agg_size, u16 timeout) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u16 capab; + + skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); + + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer " + "for addba request frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, da, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + else + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + + skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); + + mgmt->u.action.category = WLAN_CATEGORY_BACK; + mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; + + mgmt->u.action.u.addba_req.dialog_token = dialog_token; + capab = (u16)(1 << 1); /* bit 1 aggregation policy */ + capab |= (u16)(tid << 2); /* bit 5:2 TID number */ + capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ + + mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); + + mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); + mgmt->u.action.u.addba_req.start_seq_num = + cpu_to_le16(start_seq_num << 4); + + ieee80211_sta_tx(sdata, skb, 0); +} + +void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, + u16 initiator, u16 reason_code) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u16 params; + + skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); + + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer " + "for delba frame\n", sdata->dev->name); + return; + } + + skb_reserve(skb, local->hw.extra_tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, da, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + else + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + + skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); + + mgmt->u.action.category = WLAN_CATEGORY_BACK; + mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; + params = (u16)(initiator << 11); /* bit 11 initiator */ + params |= (u16)(tid << 12); /* bit 15:12 TID number */ + + mgmt->u.action.u.delba.params = cpu_to_le16(params); + mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); + + ieee80211_sta_tx(sdata, skb, 0); +} + +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_bar *bar; + u16 bar_control = 0; + + skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer for " + "bar frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); + memset(bar, 0, sizeof(*bar)); + bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_BACK_REQ); + memcpy(bar->ra, ra, ETH_ALEN); + memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); + bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; + bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; + bar_control |= (u16)(tid << 12); + bar->control = cpu_to_le16(bar_control); + bar->start_seq_num = cpu_to_le16(ssn); + + ieee80211_sta_tx(sdata, skb, 0); +} + +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, + u16 initiator, u16 reason) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_hw *hw = &local->hw; + struct sta_info *sta; + int ret, i; + DECLARE_MAC_BUF(mac); + + rcu_read_lock(); + + sta = sta_info_get(local, ra); + if (!sta) { + rcu_read_unlock(); + return; + } + + /* check if TID is in operational state */ + spin_lock_bh(&sta->lock); + if (sta->ampdu_mlme.tid_state_rx[tid] + != HT_AGG_STATE_OPERATIONAL) { + spin_unlock_bh(&sta->lock); + rcu_read_unlock(); + return; + } + sta->ampdu_mlme.tid_state_rx[tid] = + HT_AGG_STATE_REQ_STOP_BA_MSK | + (initiator << HT_AGG_STATE_INITIATOR_SHIFT); + spin_unlock_bh(&sta->lock); + + /* stop HW Rx aggregation. ampdu_action existence + * already verified in session init so we add the BUG_ON */ + BUG_ON(!local->ops->ampdu_action); + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", + print_mac(mac, ra), tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + + ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, + ra, tid, NULL); + if (ret) + printk(KERN_DEBUG "HW problem - can not stop rx " + "aggregation for tid %d\n", tid); + + /* shutdown timer has not expired */ + if (initiator != WLAN_BACK_TIMER) + del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); + + /* check if this is a self generated aggregation halt */ + if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) + ieee80211_send_delba(sdata, ra, tid, 0, reason); + + /* free the reordering buffer */ + for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { + if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { + /* release the reordered frames */ + dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); + sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; + sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; + } + } + /* free resources */ + kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); + kfree(sta->ampdu_mlme.tid_rx[tid]); + sta->ampdu_mlme.tid_rx[tid] = NULL; + sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; + + rcu_read_unlock(); +} + + +/* + * After sending add Block Ack request we activated a timer until + * add Block Ack response will arrive from the recipient. + * If this timer expires sta_addba_resp_timer_expired will be executed. + */ +void sta_addba_resp_timer_expired(unsigned long data) +{ + /* not an elegant detour, but there is no choice as the timer passes + * only one argument, and both sta_info and TID are needed, so init + * flow in sta_info_create gives the TID as data, while the timer_to_id + * array gives the sta through container_of */ + u16 tid = *(u8 *)data; + struct sta_info *temp_sta = container_of((void *)data, + struct sta_info, timer_to_tid[tid]); + + struct ieee80211_local *local = temp_sta->local; + struct ieee80211_hw *hw = &local->hw; + struct sta_info *sta; + u8 *state; + + rcu_read_lock(); + + sta = sta_info_get(local, temp_sta->addr); + if (!sta) { + rcu_read_unlock(); + return; + } + + state = &sta->ampdu_mlme.tid_state_tx[tid]; + /* check if the TID waits for addBA response */ + spin_lock_bh(&sta->lock); + if (!(*state & HT_ADDBA_REQUESTED_MSK)) { + spin_unlock_bh(&sta->lock); + *state = HT_AGG_STATE_IDLE; +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "timer expired on tid %d but we are not " + "expecting addBA response there", tid); +#endif + goto timer_expired_exit; + } + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); +#endif + + /* go through the state check in stop_BA_session */ + *state = HT_AGG_STATE_OPERATIONAL; + spin_unlock_bh(&sta->lock); + ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, + WLAN_BACK_INITIATOR); + +timer_expired_exit: + rcu_read_unlock(); +} + +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) +{ + struct ieee80211_local *local = sdata->local; + int i; + + for (i = 0; i < STA_TID_NUM; i++) { + ieee80211_stop_tx_ba_session(&local->hw, addr, i, + WLAN_BACK_INITIATOR); + ieee80211_sta_stop_rx_ba_session(sdata, addr, i, + WLAN_BACK_RECIPIENT, + WLAN_REASON_QSTA_LEAVE_QBSS); + } +} + diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index be3292bfabe3..f43ca7b88d57 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -48,20 +48,6 @@ #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 -/* mgmt header + 1 byte category code */ -#define IEEE80211_MIN_ACTION_SIZE (24 + 1) - -#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 -#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C -#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 -#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 -#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 - -/* next values represent the buffer size for A-MPDU frame. - * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */ -#define IEEE80211_MIN_AMPDU_BUF 0x8 -#define IEEE80211_MAX_AMPDU_BUF 0x40 - /* utils */ static int ecw2cw(int ecw) { @@ -389,52 +375,6 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, return changed; } -int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, - struct ieee80211_ht_info *ht_info) -{ - - if (ht_info == NULL) - return -EINVAL; - - memset(ht_info, 0, sizeof(*ht_info)); - - if (ht_cap_ie) { - u8 ampdu_info = ht_cap_ie->ampdu_params_info; - - ht_info->ht_supported = 1; - ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); - ht_info->ampdu_factor = - ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; - ht_info->ampdu_density = - (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; - memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); - } else - ht_info->ht_supported = 0; - - return 0; -} - -int ieee80211_ht_addt_info_ie_to_ht_bss_info( - struct ieee80211_ht_addt_info *ht_add_info_ie, - struct ieee80211_ht_bss_info *bss_info) -{ - if (bss_info == NULL) - return -EINVAL; - - memset(bss_info, 0, sizeof(*bss_info)); - - if (ht_add_info_ie) { - u16 op_mode; - op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); - - bss_info->primary_channel = ht_add_info_ie->control_chan; - bss_info->bss_cap = ht_add_info_ie->ht_param; - bss_info->bss_op_mode = (u8)(op_mode & 0xff); - } - - return 0; -} - static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -1118,55 +1058,6 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d return; } -void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, - u16 tid, u8 dialog_token, u16 start_seq_num, - u16 agg_size, u16 timeout) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u16 capab; - - skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - - if (!skb) { - printk(KERN_ERR "%s: failed to allocate buffer " - "for addba request frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); - else - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); - - mgmt->u.action.category = WLAN_CATEGORY_BACK; - mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; - - mgmt->u.action.u.addba_req.dialog_token = dialog_token; - capab = (u16)(1 << 1); /* bit 1 aggregation policy */ - capab |= (u16)(tid << 2); /* bit 5:2 TID number */ - capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ - - mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); - - mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); - mgmt->u.action.u.addba_req.start_seq_num = - cpu_to_le16(start_seq_num << 4); - - ieee80211_sta_tx(sdata, skb, 0); -} - /* * After accepting the AddBA Request we activated a timer, * resetting it after each frame that arrives from the originator. @@ -1396,149 +1287,6 @@ addba_resp_exit: rcu_read_unlock(); } -void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, - u16 initiator, u16 reason_code) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u16 params; - - skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - - if (!skb) { - printk(KERN_ERR "%s: failed to allocate buffer " - "for delba frame\n", sdata->dev->name); - return; - } - - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); - else - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); - - mgmt->u.action.category = WLAN_CATEGORY_BACK; - mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; - params = (u16)(initiator << 11); /* bit 11 initiator */ - params |= (u16)(tid << 12); /* bit 15:12 TID number */ - - mgmt->u.action.u.delba.params = cpu_to_le16(params); - mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - - ieee80211_sta_tx(sdata, skb, 0); -} - -void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_bar *bar; - u16 bar_control = 0; - - skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); - if (!skb) { - printk(KERN_ERR "%s: failed to allocate buffer for " - "bar frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); - memset(bar, 0, sizeof(*bar)); - bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_BACK_REQ); - memcpy(bar->ra, ra, ETH_ALEN); - memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); - bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; - bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; - bar_control |= (u16)(tid << 12); - bar->control = cpu_to_le16(bar_control); - bar->start_seq_num = cpu_to_le16(ssn); - - ieee80211_sta_tx(sdata, skb, 0); -} - -void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, - u16 initiator, u16 reason) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_hw *hw = &local->hw; - struct sta_info *sta; - int ret, i; - DECLARE_MAC_BUF(mac); - - rcu_read_lock(); - - sta = sta_info_get(local, ra); - if (!sta) { - rcu_read_unlock(); - return; - } - - /* check if TID is in operational state */ - spin_lock_bh(&sta->lock); - if (sta->ampdu_mlme.tid_state_rx[tid] - != HT_AGG_STATE_OPERATIONAL) { - spin_unlock_bh(&sta->lock); - rcu_read_unlock(); - return; - } - sta->ampdu_mlme.tid_state_rx[tid] = - HT_AGG_STATE_REQ_STOP_BA_MSK | - (initiator << HT_AGG_STATE_INITIATOR_SHIFT); - spin_unlock_bh(&sta->lock); - - /* stop HW Rx aggregation. ampdu_action existence - * already verified in session init so we add the BUG_ON */ - BUG_ON(!local->ops->ampdu_action); - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", - print_mac(mac, ra), tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, - ra, tid, NULL); - if (ret) - printk(KERN_DEBUG "HW problem - can not stop rx " - "aggregation for tid %d\n", tid); - - /* shutdown timer has not expired */ - if (initiator != WLAN_BACK_TIMER) - del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); - - /* check if this is a self generated aggregation halt */ - if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) - ieee80211_send_delba(sdata, ra, tid, 0, reason); - - /* free the reordering buffer */ - for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { - if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { - /* release the reordered frames */ - dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); - sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; - sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; - } - } - /* free resources */ - kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); - kfree(sta->ampdu_mlme.tid_rx[tid]); - sta->ampdu_mlme.tid_rx[tid] = NULL; - sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; - - rcu_read_unlock(); -} - - static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -1582,75 +1330,6 @@ static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); } -/* - * After sending add Block Ack request we activated a timer until - * add Block Ack response will arrive from the recipient. - * If this timer expires sta_addba_resp_timer_expired will be executed. - */ -void sta_addba_resp_timer_expired(unsigned long data) -{ - /* not an elegant detour, but there is no choice as the timer passes - * only one argument, and both sta_info and TID are needed, so init - * flow in sta_info_create gives the TID as data, while the timer_to_id - * array gives the sta through container_of */ - u16 tid = *(u8 *)data; - struct sta_info *temp_sta = container_of((void *)data, - struct sta_info, timer_to_tid[tid]); - - struct ieee80211_local *local = temp_sta->local; - struct ieee80211_hw *hw = &local->hw; - struct sta_info *sta; - u8 *state; - - rcu_read_lock(); - - sta = sta_info_get(local, temp_sta->addr); - if (!sta) { - rcu_read_unlock(); - return; - } - - state = &sta->ampdu_mlme.tid_state_tx[tid]; - /* check if the TID waits for addBA response */ - spin_lock_bh(&sta->lock); - if (!(*state & HT_ADDBA_REQUESTED_MSK)) { - spin_unlock_bh(&sta->lock); - *state = HT_AGG_STATE_IDLE; -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "timer expired on tid %d but we are not " - "expecting addBA response there", tid); -#endif - goto timer_expired_exit; - } - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); -#endif - - /* go through the state check in stop_BA_session */ - *state = HT_AGG_STATE_OPERATIONAL; - spin_unlock_bh(&sta->lock); - ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, - WLAN_BACK_INITIATOR); - -timer_expired_exit: - rcu_read_unlock(); -} - -void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) -{ - struct ieee80211_local *local = sdata->local; - int i; - - for (i = 0; i < STA_TID_NUM; i++) { - ieee80211_stop_tx_ba_session(&local->hw, addr, i, - WLAN_BACK_INITIATOR); - ieee80211_sta_stop_rx_ba_session(sdata, addr, i, - WLAN_BACK_RECIPIENT, - WLAN_REASON_QSTA_LEAVE_QBSS); - } -} - static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, struct ieee80211_msrment_ie *request_ie, const u8 *da, const u8 *bssid, -- cgit v1.2.3 From bacac545f10f2bf6e5ceff0d8e2b82dfc493602a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:44:29 +0200 Subject: mac80211: move some HT code out of main.c Now that I've created ht.c, I can move the aggregation code from main.c into it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ht.c | 377 +++++++++++++++++++++++++++++++++++++++++++++++++++- net/mac80211/main.c | 373 --------------------------------------------------- 2 files changed, 375 insertions(+), 375 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 5ccf1bc17466..c72b3fe3ccdb 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -2,8 +2,8 @@ * HT handling * * Copyright 2003, Jouni Malinen - * Copyright 2004, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. + * Copyright 2002-2005, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2008, Intel Corporation @@ -18,6 +18,7 @@ #include #include "ieee80211_i.h" #include "sta_info.h" +#include "wme.h" int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_ht_info *ht_info) @@ -326,3 +327,375 @@ void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 } } +int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct sta_info *sta; + struct ieee80211_sub_if_data *sdata; + u16 start_seq_num; + u8 *state; + int ret; + DECLARE_MAC_BUF(mac); + + if (tid >= STA_TID_NUM) + return -EINVAL; + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", + print_mac(mac, ra), tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + + rcu_read_lock(); + + sta = sta_info_get(local, ra); + if (!sta) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Could not find the station\n"); +#endif + ret = -ENOENT; + goto exit; + } + + spin_lock_bh(&sta->lock); + + /* we have tried too many times, receiver does not want A-MPDU */ + if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { + ret = -EBUSY; + goto err_unlock_sta; + } + + state = &sta->ampdu_mlme.tid_state_tx[tid]; + /* check if the TID is not in aggregation flow already */ + if (*state != HT_AGG_STATE_IDLE) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "BA request denied - session is not " + "idle on tid %u\n", tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + ret = -EAGAIN; + goto err_unlock_sta; + } + + /* prepare A-MPDU MLME for Tx aggregation */ + sta->ampdu_mlme.tid_tx[tid] = + kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); + if (!sta->ampdu_mlme.tid_tx[tid]) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_ERR "allocate tx mlme to tid %d failed\n", + tid); +#endif + ret = -ENOMEM; + goto err_unlock_sta; + } + /* Tx timer */ + sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = + sta_addba_resp_timer_expired; + sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = + (unsigned long)&sta->timer_to_tid[tid]; + init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); + + /* create a new queue for this aggregation */ + ret = ieee80211_ht_agg_queue_add(local, sta, tid); + + /* case no queue is available to aggregation + * don't switch to aggregation */ + if (ret) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "BA request denied - queue unavailable for" + " tid %d\n", tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + goto err_unlock_queue; + } + sdata = sta->sdata; + + /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the + * call back right away, it must see that the flow has begun */ + *state |= HT_ADDBA_REQUESTED_MSK; + + /* This is slightly racy because the queue isn't stopped */ + start_seq_num = sta->tid_seq[tid]; + + if (local->ops->ampdu_action) + ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, + ra, tid, &start_seq_num); + + if (ret) { + /* No need to requeue the packets in the agg queue, since we + * held the tx lock: no packet could be enqueued to the newly + * allocated queue */ + ieee80211_ht_agg_queue_remove(local, sta, tid, 0); +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "BA request denied - HW unavailable for" + " tid %d\n", tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + *state = HT_AGG_STATE_IDLE; + goto err_unlock_queue; + } + + /* Will put all the packets in the new SW queue */ + ieee80211_requeue(local, ieee802_1d_to_ac[tid]); + spin_unlock_bh(&sta->lock); + + /* send an addBA request */ + sta->ampdu_mlme.dialog_token_allocator++; + sta->ampdu_mlme.tid_tx[tid]->dialog_token = + sta->ampdu_mlme.dialog_token_allocator; + sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; + + + ieee80211_send_addba_request(sta->sdata, ra, tid, + sta->ampdu_mlme.tid_tx[tid]->dialog_token, + sta->ampdu_mlme.tid_tx[tid]->ssn, + 0x40, 5000); + /* activate the timer for the recipient's addBA response */ + sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = + jiffies + ADDBA_RESP_INTERVAL; + add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); +#endif + goto exit; + +err_unlock_queue: + kfree(sta->ampdu_mlme.tid_tx[tid]); + sta->ampdu_mlme.tid_tx[tid] = NULL; + ret = -EBUSY; +err_unlock_sta: + spin_unlock_bh(&sta->lock); +exit: + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ieee80211_start_tx_ba_session); + +int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, + u8 *ra, u16 tid, + enum ieee80211_back_parties initiator) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct sta_info *sta; + u8 *state; + int ret = 0; + DECLARE_MAC_BUF(mac); + + if (tid >= STA_TID_NUM) + return -EINVAL; + + rcu_read_lock(); + sta = sta_info_get(local, ra); + if (!sta) { + rcu_read_unlock(); + return -ENOENT; + } + + /* check if the TID is in aggregation */ + state = &sta->ampdu_mlme.tid_state_tx[tid]; + spin_lock_bh(&sta->lock); + + if (*state != HT_AGG_STATE_OPERATIONAL) { + ret = -ENOENT; + goto stop_BA_exit; + } + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", + print_mac(mac, ra), tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + + ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); + + *state = HT_AGG_STATE_REQ_STOP_BA_MSK | + (initiator << HT_AGG_STATE_INITIATOR_SHIFT); + + if (local->ops->ampdu_action) + ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, + ra, tid, NULL); + + /* case HW denied going back to legacy */ + if (ret) { + WARN_ON(ret != -EBUSY); + *state = HT_AGG_STATE_OPERATIONAL; + ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); + goto stop_BA_exit; + } + +stop_BA_exit: + spin_unlock_bh(&sta->lock); + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); + +void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct sta_info *sta; + u8 *state; + DECLARE_MAC_BUF(mac); + + if (tid >= STA_TID_NUM) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", + tid, STA_TID_NUM); +#endif + return; + } + + rcu_read_lock(); + sta = sta_info_get(local, ra); + if (!sta) { + rcu_read_unlock(); +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Could not find station: %s\n", + print_mac(mac, ra)); +#endif + return; + } + + state = &sta->ampdu_mlme.tid_state_tx[tid]; + spin_lock_bh(&sta->lock); + + if (!(*state & HT_ADDBA_REQUESTED_MSK)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", + *state); +#endif + spin_unlock_bh(&sta->lock); + rcu_read_unlock(); + return; + } + + WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); + + *state |= HT_ADDBA_DRV_READY_MSK; + + if (*state == HT_AGG_STATE_OPERATIONAL) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); +#endif + ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); + } + spin_unlock_bh(&sta->lock); + rcu_read_unlock(); +} +EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); + +void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct sta_info *sta; + u8 *state; + int agg_queue; + DECLARE_MAC_BUF(mac); + + if (tid >= STA_TID_NUM) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", + tid, STA_TID_NUM); +#endif + return; + } + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", + print_mac(mac, ra), tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + + rcu_read_lock(); + sta = sta_info_get(local, ra); + if (!sta) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Could not find station: %s\n", + print_mac(mac, ra)); +#endif + rcu_read_unlock(); + return; + } + state = &sta->ampdu_mlme.tid_state_tx[tid]; + + /* NOTE: no need to use sta->lock in this state check, as + * ieee80211_stop_tx_ba_session will let only one stop call to + * pass through per sta/tid + */ + if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); +#endif + rcu_read_unlock(); + return; + } + + if (*state & HT_AGG_STATE_INITIATOR_MSK) + ieee80211_send_delba(sta->sdata, ra, tid, + WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); + + agg_queue = sta->tid_to_tx_q[tid]; + + ieee80211_ht_agg_queue_remove(local, sta, tid, 1); + + /* We just requeued the all the frames that were in the + * removed queue, and since we might miss a softirq we do + * netif_schedule_queue. ieee80211_wake_queue is not used + * here as this queue is not necessarily stopped + */ + netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); + spin_lock_bh(&sta->lock); + *state = HT_AGG_STATE_IDLE; + sta->ampdu_mlme.addba_req_num[tid] = 0; + kfree(sta->ampdu_mlme.tid_tx[tid]); + sta->ampdu_mlme.tid_tx[tid] = NULL; + spin_unlock_bh(&sta->lock); + + rcu_read_unlock(); +} +EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); + +void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, + const u8 *ra, u16 tid) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_ra_tid *ra_tid; + struct sk_buff *skb = dev_alloc_skb(0); + + if (unlikely(!skb)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_WARNING "%s: Not enough memory, " + "dropping start BA session", skb->dev->name); +#endif + return; + } + ra_tid = (struct ieee80211_ra_tid *) &skb->cb; + memcpy(&ra_tid->ra, ra, ETH_ALEN); + ra_tid->tid = tid; + + skb->pkt_type = IEEE80211_ADDBA_MSG; + skb_queue_tail(&local->skb_queue, skb); + tasklet_schedule(&local->tasklet); +} +EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); + +void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, + const u8 *ra, u16 tid) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_ra_tid *ra_tid; + struct sk_buff *skb = dev_alloc_skb(0); + + if (unlikely(!skb)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_WARNING "%s: Not enough memory, " + "dropping stop BA session", skb->dev->name); +#endif + return; + } + ra_tid = (struct ieee80211_ra_tid *) &skb->cb; + memcpy(&ra_tid->ra, ra, ETH_ALEN); + ra_tid->tid = tid; + + skb->pkt_type = IEEE80211_DELBA_MSG; + skb_queue_tail(&local->skb_queue, skb); + tasklet_schedule(&local->tasklet); +} +EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6df4a2e15098..f90254a5948e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -593,379 +593,6 @@ static int ieee80211_stop(struct net_device *dev) return 0; } -int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct sta_info *sta; - struct ieee80211_sub_if_data *sdata; - u16 start_seq_num; - u8 *state; - int ret; - DECLARE_MAC_BUF(mac); - - if (tid >= STA_TID_NUM) - return -EINVAL; - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", - print_mac(mac, ra), tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - - rcu_read_lock(); - - sta = sta_info_get(local, ra); - if (!sta) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Could not find the station\n"); -#endif - ret = -ENOENT; - goto exit; - } - - spin_lock_bh(&sta->lock); - - /* we have tried too many times, receiver does not want A-MPDU */ - if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { - ret = -EBUSY; - goto err_unlock_sta; - } - - state = &sta->ampdu_mlme.tid_state_tx[tid]; - /* check if the TID is not in aggregation flow already */ - if (*state != HT_AGG_STATE_IDLE) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "BA request denied - session is not " - "idle on tid %u\n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - ret = -EAGAIN; - goto err_unlock_sta; - } - - /* prepare A-MPDU MLME for Tx aggregation */ - sta->ampdu_mlme.tid_tx[tid] = - kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); - if (!sta->ampdu_mlme.tid_tx[tid]) { -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_ERR "allocate tx mlme to tid %d failed\n", - tid); -#endif - ret = -ENOMEM; - goto err_unlock_sta; - } - /* Tx timer */ - sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = - sta_addba_resp_timer_expired; - sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = - (unsigned long)&sta->timer_to_tid[tid]; - init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); - - /* create a new queue for this aggregation */ - ret = ieee80211_ht_agg_queue_add(local, sta, tid); - - /* case no queue is available to aggregation - * don't switch to aggregation */ - if (ret) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "BA request denied - queue unavailable for" - " tid %d\n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - goto err_unlock_queue; - } - sdata = sta->sdata; - - /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the - * call back right away, it must see that the flow has begun */ - *state |= HT_ADDBA_REQUESTED_MSK; - - /* This is slightly racy because the queue isn't stopped */ - start_seq_num = sta->tid_seq[tid]; - - if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, - ra, tid, &start_seq_num); - - if (ret) { - /* No need to requeue the packets in the agg queue, since we - * held the tx lock: no packet could be enqueued to the newly - * allocated queue */ - ieee80211_ht_agg_queue_remove(local, sta, tid, 0); -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "BA request denied - HW unavailable for" - " tid %d\n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - *state = HT_AGG_STATE_IDLE; - goto err_unlock_queue; - } - - /* Will put all the packets in the new SW queue */ - ieee80211_requeue(local, ieee802_1d_to_ac[tid]); - spin_unlock_bh(&sta->lock); - - /* send an addBA request */ - sta->ampdu_mlme.dialog_token_allocator++; - sta->ampdu_mlme.tid_tx[tid]->dialog_token = - sta->ampdu_mlme.dialog_token_allocator; - sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; - - - ieee80211_send_addba_request(sta->sdata, ra, tid, - sta->ampdu_mlme.tid_tx[tid]->dialog_token, - sta->ampdu_mlme.tid_tx[tid]->ssn, - 0x40, 5000); - /* activate the timer for the recipient's addBA response */ - sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = - jiffies + ADDBA_RESP_INTERVAL; - add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); -#endif - goto exit; - -err_unlock_queue: - kfree(sta->ampdu_mlme.tid_tx[tid]); - sta->ampdu_mlme.tid_tx[tid] = NULL; - ret = -EBUSY; -err_unlock_sta: - spin_unlock_bh(&sta->lock); -exit: - rcu_read_unlock(); - return ret; -} -EXPORT_SYMBOL(ieee80211_start_tx_ba_session); - -int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, - u8 *ra, u16 tid, - enum ieee80211_back_parties initiator) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct sta_info *sta; - u8 *state; - int ret = 0; - DECLARE_MAC_BUF(mac); - - if (tid >= STA_TID_NUM) - return -EINVAL; - - rcu_read_lock(); - sta = sta_info_get(local, ra); - if (!sta) { - rcu_read_unlock(); - return -ENOENT; - } - - /* check if the TID is in aggregation */ - state = &sta->ampdu_mlme.tid_state_tx[tid]; - spin_lock_bh(&sta->lock); - - if (*state != HT_AGG_STATE_OPERATIONAL) { - ret = -ENOENT; - goto stop_BA_exit; - } - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", - print_mac(mac, ra), tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - - ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); - - *state = HT_AGG_STATE_REQ_STOP_BA_MSK | - (initiator << HT_AGG_STATE_INITIATOR_SHIFT); - - if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, - ra, tid, NULL); - - /* case HW denied going back to legacy */ - if (ret) { - WARN_ON(ret != -EBUSY); - *state = HT_AGG_STATE_OPERATIONAL; - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); - goto stop_BA_exit; - } - -stop_BA_exit: - spin_unlock_bh(&sta->lock); - rcu_read_unlock(); - return ret; -} -EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); - -void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct sta_info *sta; - u8 *state; - DECLARE_MAC_BUF(mac); - - if (tid >= STA_TID_NUM) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", - tid, STA_TID_NUM); -#endif - return; - } - - rcu_read_lock(); - sta = sta_info_get(local, ra); - if (!sta) { - rcu_read_unlock(); -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Could not find station: %s\n", - print_mac(mac, ra)); -#endif - return; - } - - state = &sta->ampdu_mlme.tid_state_tx[tid]; - spin_lock_bh(&sta->lock); - - if (!(*state & HT_ADDBA_REQUESTED_MSK)) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", - *state); -#endif - spin_unlock_bh(&sta->lock); - rcu_read_unlock(); - return; - } - - WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); - - *state |= HT_ADDBA_DRV_READY_MSK; - - if (*state == HT_AGG_STATE_OPERATIONAL) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); -#endif - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); - } - spin_unlock_bh(&sta->lock); - rcu_read_unlock(); -} -EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); - -void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct sta_info *sta; - u8 *state; - int agg_queue; - DECLARE_MAC_BUF(mac); - - if (tid >= STA_TID_NUM) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", - tid, STA_TID_NUM); -#endif - return; - } - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", - print_mac(mac, ra), tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - - rcu_read_lock(); - sta = sta_info_get(local, ra); - if (!sta) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Could not find station: %s\n", - print_mac(mac, ra)); -#endif - rcu_read_unlock(); - return; - } - state = &sta->ampdu_mlme.tid_state_tx[tid]; - - /* NOTE: no need to use sta->lock in this state check, as - * ieee80211_stop_tx_ba_session will let only one stop call to - * pass through per sta/tid - */ - if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); -#endif - rcu_read_unlock(); - return; - } - - if (*state & HT_AGG_STATE_INITIATOR_MSK) - ieee80211_send_delba(sta->sdata, ra, tid, - WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); - - agg_queue = sta->tid_to_tx_q[tid]; - - ieee80211_ht_agg_queue_remove(local, sta, tid, 1); - - /* We just requeued the all the frames that were in the - * removed queue, and since we might miss a softirq we do - * netif_schedule_queue. ieee80211_wake_queue is not used - * here as this queue is not necessarily stopped - */ - netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); - spin_lock_bh(&sta->lock); - *state = HT_AGG_STATE_IDLE; - sta->ampdu_mlme.addba_req_num[tid] = 0; - kfree(sta->ampdu_mlme.tid_tx[tid]); - sta->ampdu_mlme.tid_tx[tid] = NULL; - spin_unlock_bh(&sta->lock); - - rcu_read_unlock(); -} -EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); - -void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, - const u8 *ra, u16 tid) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_ra_tid *ra_tid; - struct sk_buff *skb = dev_alloc_skb(0); - - if (unlikely(!skb)) { -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_WARNING "%s: Not enough memory, " - "dropping start BA session", skb->dev->name); -#endif - return; - } - ra_tid = (struct ieee80211_ra_tid *) &skb->cb; - memcpy(&ra_tid->ra, ra, ETH_ALEN); - ra_tid->tid = tid; - - skb->pkt_type = IEEE80211_ADDBA_MSG; - skb_queue_tail(&local->skb_queue, skb); - tasklet_schedule(&local->tasklet); -} -EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); - -void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, - const u8 *ra, u16 tid) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_ra_tid *ra_tid; - struct sk_buff *skb = dev_alloc_skb(0); - - if (unlikely(!skb)) { -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_WARNING "%s: Not enough memory, " - "dropping stop BA session", skb->dev->name); -#endif - return; - } - ra_tid = (struct ieee80211_ra_tid *) &skb->cb; - memcpy(&ra_tid->ra, ra, ETH_ALEN); - ra_tid->tid = tid; - - skb->pkt_type = IEEE80211_DELBA_MSG; - skb_queue_tail(&local->skb_queue, skb); - tasklet_schedule(&local->tasklet); -} -EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); - static void ieee80211_set_multicast_list(struct net_device *dev) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); -- cgit v1.2.3 From 9116dd01120e249dc2e84e6edecd7ad7f828680f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:47:23 +0200 Subject: mac80211: clarify scan request When a scan is requested for non-STA interfaces, we simply fire off a scan, but for STA interfaces we shouldn't because they could be in the middle of an association. This clarifies the corresponding code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/scan.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 1beefb5ad6fb..9f6120150120 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -674,23 +674,32 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct ieee80211_local *local = sdata->local; + struct ieee80211_if_sta *ifsta; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return ieee80211_sta_start_scan(sdata, ssid, ssid_len); + /* + * STA has a state machine that might need to defer scanning + * while it's trying to associate/authenticate, therefore we + * queue it up to the state machine in that case. + */ + if (local->sta_sw_scanning || local->sta_hw_scanning) { if (local->scan_sdata == sdata) return 0; return -EBUSY; } + ifsta = &sdata->u.sta; + ifsta->scan_ssid_len = ssid_len; if (ssid_len) memcpy(ifsta->scan_ssid, ssid, ssid_len); set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); queue_work(local->hw.workqueue, &ifsta->work); + return 0; } -- cgit v1.2.3 From a0fe8b3349bdee27065b57cdceb2ca53c1487866 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 8 Sep 2008 17:58:23 +0200 Subject: mac80211: simplify scan start ieee80211_sta_start_scan() can very well take a non-NULL ssid pointer with a zero ssid_len. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f43ca7b88d57..f4cbe5cc56c5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3052,10 +3052,7 @@ void ieee80211_sta_work(struct work_struct *work) ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { - if (ifsta->scan_ssid_len) - ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); - else - ieee80211_sta_start_scan(sdata, NULL, 0); + ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); return; } -- cgit v1.2.3 From b079ada7dd11cf82c3157a51c205c3d88321c704 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 09:32:59 +0200 Subject: mac80211: remove useless 'ibss' parameter Ever since we refactored beaconing to not be controlled by a fake queue this parameter to ieee80211_sta_def_wmm_params has been unused. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f4cbe5cc56c5..b1815c1ee6d3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -188,8 +188,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, /* MLME */ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_bss *bss, - int ibss) + struct ieee80211_sta_bss *bss) { struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; @@ -1849,7 +1848,7 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, } ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; - ieee80211_sta_def_wmm_params(sdata, bss, 1); + ieee80211_sta_def_wmm_params(sdata, bss); ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); @@ -2932,7 +2931,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, ieee80211_sta_set_ssid(sdata, selected->ssid, selected->ssid_len); ieee80211_sta_set_bssid(sdata, selected->bssid); - ieee80211_sta_def_wmm_params(sdata, selected, 0); + ieee80211_sta_def_wmm_params(sdata, selected); /* Send out direct probe if no probe resp was received or * the one we have is outdated -- cgit v1.2.3 From 9ac19a9084001695479a6d6dd67443cc5fb1df2f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 10:57:09 +0200 Subject: mac80211: reorder frame code in mlme This reorders all frame sending functions to be at the top of the file. When reading the file, I tend to be looking at either the frame code or the state machine, and having them mixed in the file is confusing. When all frame sending is at the top the remainder of the file is more readable, in my opinion. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 884 ++++++++++++++++++++++++++-------------------------- 1 file changed, 441 insertions(+), 443 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b1815c1ee6d3..e917e1b72631 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -74,6 +74,27 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) return NULL; } +static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, + struct ieee80211_supported_band *sband, + u64 *rates) +{ + int i, j, count; + *rates = 0; + count = 0; + for (i = 0; i < bss->supp_rates_len; i++) { + int rate = (bss->supp_rates[i] & 0x7F) * 5; + + for (j = 0; j < sband->n_bitrates; j++) + if (sband->bitrates[j].bitrate == rate) { + *rates |= BIT(j); + count++; + break; + } + } + + return count; +} + /* frame sending functions */ void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt) @@ -186,6 +207,364 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ieee80211_sta_tx(sdata, skb, 0); } +static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u8 *pos, *ies, *ht_add_ie; + int i, len, count, rates_len, supp_rates_len; + u16 capab; + struct ieee80211_sta_bss *bss; + int wmm = 0; + struct ieee80211_supported_band *sband; + u64 rates = 0; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + 200 + ifsta->extra_ie_len + + ifsta->ssid_len); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + capab = ifsta->capab; + + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) { + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; + } + + bss = ieee80211_rx_bss_get(local, ifsta->bssid, + local->hw.conf.channel->center_freq, + ifsta->ssid, ifsta->ssid_len); + if (bss) { + if (bss->capability & WLAN_CAPABILITY_PRIVACY) + capab |= WLAN_CAPABILITY_PRIVACY; + if (bss->wmm_used) + wmm = 1; + + /* get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode) */ + rates_len = ieee80211_compatible_rates(bss, sband, &rates); + + if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && + (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) + capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; + + ieee80211_rx_bss_put(local, bss); + } else { + rates = ~0; + rates_len = sband->n_bitrates; + } + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + + if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { + skb_put(skb, 10); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_REASSOC_REQ); + mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); + mgmt->u.reassoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); + memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid, + ETH_ALEN); + } else { + skb_put(skb, 4); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ASSOC_REQ); + mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); + mgmt->u.reassoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); + } + + /* SSID */ + ies = pos = skb_put(skb, 2 + ifsta->ssid_len); + *pos++ = WLAN_EID_SSID; + *pos++ = ifsta->ssid_len; + memcpy(pos, ifsta->ssid, ifsta->ssid_len); + + /* add all rates which were marked to be used above */ + supp_rates_len = rates_len; + if (supp_rates_len > 8) + supp_rates_len = 8; + + len = sband->n_bitrates; + pos = skb_put(skb, supp_rates_len + 2); + *pos++ = WLAN_EID_SUPP_RATES; + *pos++ = supp_rates_len; + + count = 0; + for (i = 0; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + if (++count == 8) + break; + } + } + + if (rates_len > count) { + pos = skb_put(skb, rates_len - count + 2); + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = rates_len - count; + + for (i++; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + } + } + + if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { + /* 1. power capabilities */ + pos = skb_put(skb, 4); + *pos++ = WLAN_EID_PWR_CAPABILITY; + *pos++ = 2; + *pos++ = 0; /* min tx power */ + *pos++ = local->hw.conf.channel->max_power; /* max tx power */ + + /* 2. supported channels */ + /* TODO: get this in reg domain format */ + pos = skb_put(skb, 2 * sband->n_channels + 2); + *pos++ = WLAN_EID_SUPPORTED_CHANNELS; + *pos++ = 2 * sband->n_channels; + for (i = 0; i < sband->n_channels; i++) { + *pos++ = ieee80211_frequency_to_channel( + sband->channels[i].center_freq); + *pos++ = 1; /* one channel in the subband*/ + } + } + + if (ifsta->extra_ie) { + pos = skb_put(skb, ifsta->extra_ie_len); + memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len); + } + + if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { + pos = skb_put(skb, 9); + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 7; /* len */ + *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ + *pos++ = 0x50; + *pos++ = 0xf2; + *pos++ = 2; /* WME */ + *pos++ = 0; /* WME info */ + *pos++ = 1; /* WME ver */ + *pos++ = 0; + } + + /* wmm support is a must to HT */ + if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && + sband->ht_info.ht_supported && + (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { + struct ieee80211_ht_addt_info *ht_add_info = + (struct ieee80211_ht_addt_info *)ht_add_ie; + u16 cap = sband->ht_info.cap; + __le16 tmp; + u32 flags = local->hw.conf.channel->flags; + + switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { + case IEEE80211_HT_IE_CHA_SEC_ABOVE: + if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + case IEEE80211_HT_IE_CHA_SEC_BELOW: + if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + } + + tmp = cpu_to_le16(cap); + pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + /* TODO: needs a define here for << 2 */ + *pos++ = sband->ht_info.ampdu_factor | + (sband->ht_info.ampdu_density << 2); + memcpy(pos, sband->ht_info.supp_mcs_set, 16); + } + + kfree(ifsta->assocreq_ies); + ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; + ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); + if (ifsta->assocreq_ies) + memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); + + ieee80211_sta_tx(sdata, skb, 0); +} + + +static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta, u16 reason) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DEAUTH); + skb_put(skb, 2); + mgmt->u.deauth.reason_code = cpu_to_le16(reason); + + ieee80211_sta_tx(sdata, skb, 0); +} + +static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta, u16 reason) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DISASSOC); + skb_put(skb, 2); + mgmt->u.disassoc.reason_code = cpu_to_le16(reason); + + ieee80211_sta_tx(sdata, skb, 0); +} + +static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, + u8 dialog_token, u16 status, u16 policy, + u16 buf_size, u16 timeout) +{ + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u16 capab; + + skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); + + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer " + "for addba resp frame\n", sdata->dev->name); + return; + } + + skb_reserve(skb, local->hw.extra_tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, da, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + else + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + + skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); + mgmt->u.action.category = WLAN_CATEGORY_BACK; + mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; + mgmt->u.action.u.addba_resp.dialog_token = dialog_token; + + capab = (u16)(policy << 1); /* bit 1 aggregation policy */ + capab |= (u16)(tid << 2); /* bit 5:2 TID number */ + capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ + + mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); + mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); + mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); + + ieee80211_sta_tx(sdata, skb, 0); +} + +static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, + struct ieee80211_msrment_ie *request_ie, + const u8 *da, const u8 *bssid, + u8 dialog_token) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *msr_report; + + skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + + sizeof(struct ieee80211_msrment_ie)); + + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer for " + "measurement report frame\n", sdata->dev->name); + return; + } + + skb_reserve(skb, local->hw.extra_tx_headroom); + msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); + memset(msr_report, 0, 24); + memcpy(msr_report->da, da, ETH_ALEN); + memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(msr_report->bssid, bssid, ETH_ALEN); + msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + + skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); + msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; + msr_report->u.action.u.measurement.action_code = + WLAN_ACTION_SPCT_MSR_RPRT; + msr_report->u.action.u.measurement.dialog_token = dialog_token; + + msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; + msr_report->u.action.u.measurement.length = + sizeof(struct ieee80211_msrment_ie); + + memset(&msr_report->u.action.u.measurement.msr_elem, 0, + sizeof(struct ieee80211_msrment_ie)); + msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; + msr_report->u.action.u.measurement.msr_elem.mode |= + IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; + msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; + + ieee80211_sta_tx(sdata, skb, 0); +} + /* MLME */ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss) @@ -429,379 +808,85 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->bss_conf.dtim_period = bss->dtim_period; changed |= ieee80211_handle_bss_capability(sdata, bss); - - ieee80211_rx_bss_put(local, bss); - } - - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { - changed |= BSS_CHANGED_HT; - sdata->bss_conf.assoc_ht = 1; - sdata->bss_conf.ht_conf = &conf->ht_conf; - sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; - } - - ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; - memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_send_associnfo(sdata, ifsta); - - ifsta->last_probe = jiffies; - ieee80211_led_assoc(local, 1); - - sdata->bss_conf.assoc = 1; - ieee80211_bss_info_change_notify(sdata, changed); - - netif_tx_start_all_queues(sdata->dev); - netif_carrier_on(sdata->dev); - - ieee80211_sta_send_apinfo(sdata, ifsta); -} - -static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - DECLARE_MAC_BUF(mac); - - ifsta->direct_probe_tries++; - if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", - sdata->dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_STA_MLME_DISABLED; - return; - } - - printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", - sdata->dev->name, print_mac(mac, ifsta->bssid), - ifsta->direct_probe_tries); - - ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; - - set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); - - /* Direct probe is sent to broadcast address as some APs - * will not answer to direct packet in unassociated state. - */ - ieee80211_send_probe_req(sdata, NULL, - ifsta->ssid, ifsta->ssid_len); - - mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); -} - - -static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - DECLARE_MAC_BUF(mac); - - ifsta->auth_tries++; - if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: authentication with AP %s" - " timed out\n", - sdata->dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_STA_MLME_DISABLED; - return; - } - - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; - printk(KERN_DEBUG "%s: authenticate with AP %s\n", - sdata->dev->name, print_mac(mac, ifsta->bssid)); - - ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); - - mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); -} - -static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, - struct ieee80211_supported_band *sband, - u64 *rates) -{ - int i, j, count; - *rates = 0; - count = 0; - for (i = 0; i < bss->supp_rates_len; i++) { - int rate = (bss->supp_rates[i] & 0x7F) * 5; - - for (j = 0; j < sband->n_bitrates; j++) - if (sband->bitrates[j].bitrate == rate) { - *rates |= BIT(j); - count++; - break; - } - } - - return count; -} - -static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos, *ies, *ht_add_ie; - int i, len, count, rates_len, supp_rates_len; - u16 capab; - struct ieee80211_sta_bss *bss; - int wmm = 0; - struct ieee80211_supported_band *sband; - u64 rates = 0; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 200 + ifsta->extra_ie_len + - ifsta->ssid_len); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - capab = ifsta->capab; - - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) { - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - } - - bss = ieee80211_rx_bss_get(local, ifsta->bssid, - local->hw.conf.channel->center_freq, - ifsta->ssid, ifsta->ssid_len); - if (bss) { - if (bss->capability & WLAN_CAPABILITY_PRIVACY) - capab |= WLAN_CAPABILITY_PRIVACY; - if (bss->wmm_used) - wmm = 1; - - /* get all rates supported by the device and the AP as - * some APs don't like getting a superset of their rates - * in the association request (e.g. D-Link DAP 1353 in - * b-only mode) */ - rates_len = ieee80211_compatible_rates(bss, sband, &rates); - - if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && - (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) - capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; - - ieee80211_rx_bss_put(local, bss); - } else { - rates = ~0; - rates_len = sband->n_bitrates; - } - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - - if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { - skb_put(skb, 10); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_REASSOC_REQ); - mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = - cpu_to_le16(local->hw.conf.listen_interval); - memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid, - ETH_ALEN); - } else { - skb_put(skb, 4); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ASSOC_REQ); - mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = - cpu_to_le16(local->hw.conf.listen_interval); - } - - /* SSID */ - ies = pos = skb_put(skb, 2 + ifsta->ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = ifsta->ssid_len; - memcpy(pos, ifsta->ssid, ifsta->ssid_len); - - /* add all rates which were marked to be used above */ - supp_rates_len = rates_len; - if (supp_rates_len > 8) - supp_rates_len = 8; - - len = sband->n_bitrates; - pos = skb_put(skb, supp_rates_len + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = supp_rates_len; - - count = 0; - for (i = 0; i < sband->n_bitrates; i++) { - if (BIT(i) & rates) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - if (++count == 8) - break; - } - } - - if (rates_len > count) { - pos = skb_put(skb, rates_len - count + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = rates_len - count; - - for (i++; i < sband->n_bitrates; i++) { - if (BIT(i) & rates) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } - } - } - - if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { - /* 1. power capabilities */ - pos = skb_put(skb, 4); - *pos++ = WLAN_EID_PWR_CAPABILITY; - *pos++ = 2; - *pos++ = 0; /* min tx power */ - *pos++ = local->hw.conf.channel->max_power; /* max tx power */ - - /* 2. supported channels */ - /* TODO: get this in reg domain format */ - pos = skb_put(skb, 2 * sband->n_channels + 2); - *pos++ = WLAN_EID_SUPPORTED_CHANNELS; - *pos++ = 2 * sband->n_channels; - for (i = 0; i < sband->n_channels; i++) { - *pos++ = ieee80211_frequency_to_channel( - sband->channels[i].center_freq); - *pos++ = 1; /* one channel in the subband*/ - } - } - - if (ifsta->extra_ie) { - pos = skb_put(skb, ifsta->extra_ie_len); - memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len); + + ieee80211_rx_bss_put(local, bss); } - if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { - pos = skb_put(skb, 9); - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 7; /* len */ - *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ - *pos++ = 0x50; - *pos++ = 0xf2; - *pos++ = 2; /* WME */ - *pos++ = 0; /* WME info */ - *pos++ = 1; /* WME ver */ - *pos++ = 0; + if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + changed |= BSS_CHANGED_HT; + sdata->bss_conf.assoc_ht = 1; + sdata->bss_conf.ht_conf = &conf->ht_conf; + sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; } - /* wmm support is a must to HT */ - if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && - sband->ht_info.ht_supported && - (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { - struct ieee80211_ht_addt_info *ht_add_info = - (struct ieee80211_ht_addt_info *)ht_add_ie; - u16 cap = sband->ht_info.cap; - __le16 tmp; - u32 flags = local->hw.conf.channel->flags; + ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; + memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); + ieee80211_sta_send_associnfo(sdata, ifsta); - switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { - case IEEE80211_HT_IE_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - case IEEE80211_HT_IE_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - } + ifsta->last_probe = jiffies; + ieee80211_led_assoc(local, 1); - tmp = cpu_to_le16(cap); - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - memset(pos, 0, sizeof(struct ieee80211_ht_cap)); - memcpy(pos, &tmp, sizeof(u16)); - pos += sizeof(u16); - /* TODO: needs a define here for << 2 */ - *pos++ = sband->ht_info.ampdu_factor | - (sband->ht_info.ampdu_density << 2); - memcpy(pos, sband->ht_info.supp_mcs_set, 16); - } + sdata->bss_conf.assoc = 1; + ieee80211_bss_info_change_notify(sdata, changed); - kfree(ifsta->assocreq_ies); - ifsta->assocreq_ies_len = (skb->data + skb->len) - ies; - ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL); - if (ifsta->assocreq_ies) - memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); + netif_tx_start_all_queues(sdata->dev); + netif_carrier_on(sdata->dev); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_sta_send_apinfo(sdata, ifsta); } - -static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, u16 reason) +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; + DECLARE_MAC_BUF(mac); - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " - "frame\n", sdata->dev->name); + ifsta->direct_probe_tries++; + if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_DEAUTH); - skb_put(skb, 2); - mgmt->u.deauth.reason_code = cpu_to_le16(reason); + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", + sdata->dev->name, print_mac(mac, ifsta->bssid), + ifsta->direct_probe_tries); - ieee80211_sta_tx(sdata, skb, 0); -} + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; -static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) -{ - if (!sdata || !sdata->default_key || - sdata->default_key->conf.alg != ALG_WEP) - return 0; - return 1; + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); + + /* Direct probe is sent to broadcast address as some APs + * will not answer to direct packet in unassociated state. + */ + ieee80211_send_probe_req(sdata, NULL, + ifsta->ssid, ifsta->ssid_len); + + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } -static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, u16 reason) + +static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; + DECLARE_MAC_BUF(mac); - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " - "frame\n", sdata->dev->name); + ifsta->auth_tries++; + if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: authentication with AP %s" + " timed out\n", + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_DISASSOC); - skb_put(skb, 2); - mgmt->u.disassoc.reason_code = cpu_to_le16(reason); + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + printk(KERN_DEBUG "%s: authenticate with AP %s\n", + sdata->dev->name, print_mac(mac, ifsta->bssid)); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); + + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, @@ -864,6 +949,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sta_info_destroy(sta); } +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) +{ + if (!sdata || !sdata->default_key || + sdata->default_key->conf.alg != ALG_WEP) + return 0; + return 1; +} + static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -1009,54 +1102,6 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, elems.challenge_len + 2, 1); } -static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, - u8 dialog_token, u16 status, u16 policy, - u16 buf_size, u16 timeout) -{ - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u16 capab; - - skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer " - "for addba resp frame\n", sdata->dev->name); - return; - } - - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); - else - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); - mgmt->u.action.category = WLAN_CATEGORY_BACK; - mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; - mgmt->u.action.u.addba_resp.dialog_token = dialog_token; - - capab = (u16)(policy << 1); /* bit 1 aggregation policy */ - capab |= (u16)(tid << 2); /* bit 5:2 TID number */ - capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ - - mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); - mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); - mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - - ieee80211_sta_tx(sdata, skb, 0); - - return; -} - /* * After accepting the AddBA Request we activated a timer, * resetting it after each frame that arrives from the originator. @@ -1329,53 +1374,6 @@ static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); } -static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, - struct ieee80211_msrment_ie *request_ie, - const u8 *da, const u8 *bssid, - u8 dialog_token) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *msr_report; - - skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + - sizeof(struct ieee80211_msrment_ie)); - - if (!skb) { - printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", sdata->dev->name); - return; - } - - skb_reserve(skb, local->hw.extra_tx_headroom); - msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); - memset(msr_report, 0, 24); - memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(msr_report->bssid, bssid, ETH_ALEN); - msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); - msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; - msr_report->u.action.u.measurement.action_code = - WLAN_ACTION_SPCT_MSR_RPRT; - msr_report->u.action.u.measurement.dialog_token = dialog_token; - - msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; - msr_report->u.action.u.measurement.length = - sizeof(struct ieee80211_msrment_ie); - - memset(&msr_report->u.action.u.measurement.msr_elem, 0, - sizeof(struct ieee80211_msrment_ie)); - msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; - msr_report->u.action.u.measurement.msr_elem.mode |= - IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; - msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - - ieee80211_sta_tx(sdata, skb, 0); -} - static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) -- cgit v1.2.3 From ef422bc0ae934e6a46dfa63f0e27cad83b94234f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 10:58:25 +0200 Subject: mac80211: consolidate deauth/disassoc deauth and disassoc frames are completely identical so there's little point in having two functions to send them rather than one that gets a parameter. This same a bit of code size. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e917e1b72631..62357a208851 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -416,17 +416,18 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } -static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, u16 reason) +static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, + u16 stype, u16 reason) { struct ieee80211_local *local = sdata->local; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " - "frame\n", sdata->dev->name); + printk(KERN_DEBUG "%s: failed to allocate buffer for " + "deauth/disassoc frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -436,42 +437,14 @@ static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_DEAUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); skb_put(skb, 2); + /* u.deauth.reason_code == u.disassoc.reason_code */ mgmt->u.deauth.reason_code = cpu_to_le16(reason); ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, u16 reason) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " - "frame\n", sdata->dev->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_DISASSOC); - skb_put(skb, 2); - mgmt->u.disassoc.reason_code = cpu_to_le16(reason); - - ieee80211_sta_tx(sdata, skb, 0); -} - static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u8 dialog_token, u16 status, u16 policy, u16 buf_size, u16 timeout) @@ -919,9 +892,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, if (self_disconnected) { if (deauth) - ieee80211_send_deauth(sdata, ifsta, reason); + ieee80211_send_deauth_disassoc(sdata, + IEEE80211_STYPE_DEAUTH, reason); else - ieee80211_send_disassoc(sdata, ifsta, reason); + ieee80211_send_deauth_disassoc(sdata, + IEEE80211_STYPE_DISASSOC, reason); } ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; -- cgit v1.2.3 From 3d35f7c6874d83063d19de0cdb4e503ff4471098 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 12:54:11 +0200 Subject: mac80211: split ieee80211_sta_def_wmm_params Cleans up the code a bit and prepares for the next patch that will use the function elsewhere. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 62357a208851..f754ad273f92 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -539,13 +539,38 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da } /* MLME */ +static void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_queue_params qparam; + int i; + + if (!local->ops->conf_tx) + return; + + memset(&qparam, 0, sizeof(qparam)); + + qparam.aifs = 2; + + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && + !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) + qparam.cw_min = 31; + else + qparam.cw_min = 15; + + qparam.cw_max = 1023; + qparam.txop = 0; + + for (i = 0; i < local_to_hw(local)->queues; i++) + local->ops->conf_tx(local_to_hw(local), i, &qparam); +} + static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss) { struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; - /* cf. IEEE 802.11 9.2.12 */ for (i = 0; i < bss->supp_rates_len; i++) if ((bss->supp_rates[i] & 0x7f) * 5 > 110) @@ -557,26 +582,7 @@ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, else sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; - - if (local->ops->conf_tx) { - struct ieee80211_tx_queue_params qparam; - - memset(&qparam, 0, sizeof(qparam)); - - qparam.aifs = 2; - - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && - !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) - qparam.cw_min = 31; - else - qparam.cw_min = 15; - - qparam.cw_max = 1023; - qparam.txop = 0; - - for (i = 0; i < local_to_hw(local)->queues; i++) - local->ops->conf_tx(local_to_hw(local), i, &qparam); - } + ieee80211_set_wmm_default(sdata); } static void ieee80211_sta_wmm_params(struct ieee80211_local *local, -- cgit v1.2.3 From 5825fe100d654fff89aa67a1e202af1f8a7f0ad0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 12:56:01 +0200 Subject: mac80211: initialise queue QoS parameters at hw start When hardware is started it might be in a confused state with respect to queue QoS parameters. This patch changes mac80211 to set sane defaults right after the hardware is brought up. Signed-off-by: Johannes Berg Cc: Michael Buesch Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/main.c | 9 ++++++++- net/mac80211/mlme.c | 26 -------------------------- net/mac80211/util.c | 26 ++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 27 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 792c09ca08e3..b10e70715db0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -987,6 +987,7 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, int rate, int erp, int short_preamble); void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr); +void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f90254a5948e..6a7f4fae18c2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -399,8 +399,15 @@ static int ieee80211_open(struct net_device *dev) atomic_inc(&local->iff_promiscs); local->open_count++; - if (need_hw_reconfig) + if (need_hw_reconfig) { ieee80211_hw_config(local); + /* + * set default queue parameters so drivers don't + * need to initialise the hardware if the hardware + * doesn't start up with sane defaults + */ + ieee80211_set_wmm_default(sdata); + } /* * ieee80211_sta_work is disabled while network interface diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f754ad273f92..c22dcd605e48 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -539,32 +539,6 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da } /* MLME */ -static void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_tx_queue_params qparam; - int i; - - if (!local->ops->conf_tx) - return; - - memset(&qparam, 0, sizeof(qparam)); - - qparam.aifs = 2; - - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && - !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) - qparam.cw_min = 31; - else - qparam.cw_min = 15; - - qparam.cw_max = 1023; - qparam.txop = 0; - - for (i = 0; i < local_to_hw(local)->queues; i++) - local->ops->conf_tx(local_to_hw(local), i, &qparam); -} - static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e19c74cada39..55be3ef5c755 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -572,3 +572,29 @@ void ieee802_11_parse_elems(u8 *start, size_t len, pos += elen; } } + +void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_queue_params qparam; + int i; + + if (!local->ops->conf_tx) + return; + + memset(&qparam, 0, sizeof(qparam)); + + qparam.aifs = 2; + + if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && + !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) + qparam.cw_min = 31; + else + qparam.cw_min = 15; + + qparam.cw_max = 1023; + qparam.txop = 0; + + for (i = 0; i < local_to_hw(local)->queues; i++) + local->ops->conf_tx(local_to_hw(local), i, &qparam); +} -- cgit v1.2.3 From de1ede7ac3bd300f9aa565d0f93f6cf9ba74bb1a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 14:42:50 +0200 Subject: mac80211: make BA session handling independent of STA mode The aggregation handling isn't dependent on anything related to our STA-mode implementation, and doesn't need to depend on it for frame processing. This patch moves the relevant code to ht.c and adds a hook in rx.c. For now, the relevant action frames are only processed in STA/IBSS modes, but that's now something we can easily change. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ht.c | 303 +++++++++++++++++++++++++++++++++++++++- net/mac80211/ieee80211_i.h | 39 +++--- net/mac80211/mlme.c | 340 --------------------------------------------- net/mac80211/rx.c | 60 ++++++++ 4 files changed, 380 insertions(+), 362 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index c72b3fe3ccdb..7e93e1079ade 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -66,9 +66,10 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( return 0; } -void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, - u16 tid, u8 dialog_token, u16 start_seq_num, - u16 agg_size, u16 timeout) +static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, + const u8 *da, u16 tid, + u8 dialog_token, u16 start_seq_num, + u16 agg_size, u16 timeout) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; @@ -115,8 +116,55 @@ void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, - u16 initiator, u16 reason_code) +static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, + u8 dialog_token, u16 status, u16 policy, + u16 buf_size, u16 timeout) +{ + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u16 capab; + + skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); + + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer " + "for addba resp frame\n", sdata->dev->name); + return; + } + + skb_reserve(skb, local->hw.extra_tx_headroom); + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, da, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + else + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + + skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); + mgmt->u.action.category = WLAN_CATEGORY_BACK; + mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; + mgmt->u.action.u.addba_resp.dialog_token = dialog_token; + + capab = (u16)(policy << 1); /* bit 1 aggregation policy */ + capab |= (u16)(tid << 2); /* bit 5:2 TID number */ + capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ + + mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); + mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); + mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); + + ieee80211_sta_tx(sdata, skb, 0); +} + +static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, + const u8 *da, u16 tid, + u16 initiator, u16 reason_code) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; @@ -263,7 +311,7 @@ void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *r * add Block Ack response will arrive from the recipient. * If this timer expires sta_addba_resp_timer_expired will be executed. */ -void sta_addba_resp_timer_expired(unsigned long data) +static void sta_addba_resp_timer_expired(unsigned long data) { /* not an elegant detour, but there is no choice as the timer passes * only one argument, and both sta_info and TID are needed, so init @@ -699,3 +747,246 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, tasklet_schedule(&local->tasklet); } EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); + +/* + * After accepting the AddBA Request we activated a timer, + * resetting it after each frame that arrives from the originator. + * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. + */ +static void sta_rx_agg_session_timer_expired(unsigned long data) +{ + /* not an elegant detour, but there is no choice as the timer passes + * only one argument, and various sta_info are needed here, so init + * flow in sta_info_create gives the TID as data, while the timer_to_id + * array gives the sta through container_of */ + u8 *ptid = (u8 *)data; + u8 *timer_to_id = ptid - *ptid; + struct sta_info *sta = container_of(timer_to_id, struct sta_info, + timer_to_tid[0]); + +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); +#endif + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, + (u16)*ptid, WLAN_BACK_TIMER, + WLAN_REASON_QSTA_TIMEOUT); +} + +void ieee80211_process_addba_request(struct ieee80211_local *local, + struct sta_info *sta, + struct ieee80211_mgmt *mgmt, + size_t len) +{ + struct ieee80211_hw *hw = &local->hw; + struct ieee80211_conf *conf = &hw->conf; + struct tid_ampdu_rx *tid_agg_rx; + u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; + u8 dialog_token; + int ret = -EOPNOTSUPP; + DECLARE_MAC_BUF(mac); + + /* extract session parameters from addba request frame */ + dialog_token = mgmt->u.action.u.addba_req.dialog_token; + timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); + start_seq_num = + le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; + + capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; + + status = WLAN_STATUS_REQUEST_DECLINED; + + /* sanity check for incoming parameters: + * check if configuration can support the BA policy + * and if buffer size does not exceeds max value */ + if (((ba_policy != 1) + && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) + || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { + status = WLAN_STATUS_INVALID_QOS_PARAM; +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "AddBA Req with bad params from " + "%s on tid %u. policy %d, buffer size %d\n", + print_mac(mac, mgmt->sa), tid, ba_policy, + buf_size); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + goto end_no_lock; + } + /* determine default buffer size */ + if (buf_size == 0) { + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[conf->channel->band]; + buf_size = IEEE80211_MIN_AMPDU_BUF; + buf_size = buf_size << sband->ht_info.ampdu_factor; + } + + + /* examine state machine */ + spin_lock_bh(&sta->lock); + + if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "unexpected AddBA Req from " + "%s on tid %u\n", + print_mac(mac, mgmt->sa), tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + goto end; + } + + /* prepare A-MPDU MLME for Rx aggregation */ + sta->ampdu_mlme.tid_rx[tid] = + kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); + if (!sta->ampdu_mlme.tid_rx[tid]) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_ERR "allocate rx mlme to tid %d failed\n", + tid); +#endif + goto end; + } + /* rx timer */ + sta->ampdu_mlme.tid_rx[tid]->session_timer.function = + sta_rx_agg_session_timer_expired; + sta->ampdu_mlme.tid_rx[tid]->session_timer.data = + (unsigned long)&sta->timer_to_tid[tid]; + init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); + + tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; + + /* prepare reordering buffer */ + tid_agg_rx->reorder_buf = + kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); + if (!tid_agg_rx->reorder_buf) { +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_ERR "can not allocate reordering buffer " + "to tid %d\n", tid); +#endif + kfree(sta->ampdu_mlme.tid_rx[tid]); + goto end; + } + memset(tid_agg_rx->reorder_buf, 0, + buf_size * sizeof(struct sk_buff *)); + + if (local->ops->ampdu_action) + ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, + sta->addr, tid, &start_seq_num); +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + + if (ret) { + kfree(tid_agg_rx->reorder_buf); + kfree(tid_agg_rx); + sta->ampdu_mlme.tid_rx[tid] = NULL; + goto end; + } + + /* change state and send addba resp */ + sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; + tid_agg_rx->dialog_token = dialog_token; + tid_agg_rx->ssn = start_seq_num; + tid_agg_rx->head_seq_num = start_seq_num; + tid_agg_rx->buf_size = buf_size; + tid_agg_rx->timeout = timeout; + tid_agg_rx->stored_mpdu_num = 0; + status = WLAN_STATUS_SUCCESS; +end: + spin_unlock_bh(&sta->lock); + +end_no_lock: + ieee80211_send_addba_resp(sta->sdata, sta->addr, tid, + dialog_token, status, 1, buf_size, timeout); +} + +void ieee80211_process_addba_resp(struct ieee80211_local *local, + struct sta_info *sta, + struct ieee80211_mgmt *mgmt, + size_t len) +{ + struct ieee80211_hw *hw = &local->hw; + u16 capab; + u16 tid; + u8 *state; + + capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + + state = &sta->ampdu_mlme.tid_state_tx[tid]; + + spin_lock_bh(&sta->lock); + + if (!(*state & HT_ADDBA_REQUESTED_MSK)) { + spin_unlock_bh(&sta->lock); + return; + } + + if (mgmt->u.action.u.addba_resp.dialog_token != + sta->ampdu_mlme.tid_tx[tid]->dialog_token) { + spin_unlock_bh(&sta->lock); +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + return; + } + + del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) + == WLAN_STATUS_SUCCESS) { + *state |= HT_ADDBA_RECEIVED_MSK; + sta->ampdu_mlme.addba_req_num[tid] = 0; + + if (*state == HT_AGG_STATE_OPERATIONAL) + ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); + + spin_unlock_bh(&sta->lock); + } else { + sta->ampdu_mlme.addba_req_num[tid]++; + /* this will allow the state check in stop_BA_session */ + *state = HT_AGG_STATE_OPERATIONAL; + spin_unlock_bh(&sta->lock); + ieee80211_stop_tx_ba_session(hw, sta->addr, tid, + WLAN_BACK_INITIATOR); + } +} + +void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct ieee80211_mgmt *mgmt, size_t len) +{ + struct ieee80211_local *local = sdata->local; + u16 tid, params; + u16 initiator; + DECLARE_MAC_BUF(mac); + + params = le16_to_cpu(mgmt->u.action.u.delba.params); + tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; + initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11; + +#ifdef CONFIG_MAC80211_HT_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", + print_mac(mac, mgmt->sa), + initiator ? "initiator" : "recipient", tid, + mgmt->u.action.u.delba.reason_code); +#endif /* CONFIG_MAC80211_HT_DEBUG */ + + if (initiator == WLAN_BACK_INITIATOR) + ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid, + WLAN_BACK_INITIATOR, 0); + else { /* WLAN_BACK_RECIPIENT */ + spin_lock_bh(&sta->lock); + sta->ampdu_mlme.tid_state_tx[tid] = + HT_AGG_STATE_OPERATIONAL; + spin_unlock_bh(&sta->lock); + ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, + WLAN_BACK_RECIPIENT); + } +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b10e70715db0..60ec7ad27643 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -909,22 +909,6 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); -int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, - struct ieee80211_ht_info *ht_info); -int ieee80211_ht_addt_info_ie_to_ht_bss_info( - struct ieee80211_ht_addt_info *ht_add_info_ie, - struct ieee80211_ht_bss_info *bss_info); -void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, - u16 tid, u8 dialog_token, u16 start_seq_num, - u16 agg_size, u16 timeout); -void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, - u16 initiator, u16 reason_code); -void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); - -void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, - u16 tid, u16 initiator, u16 reason); -void sta_addba_resp_timer_expired(unsigned long data); -void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); u64 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); @@ -977,6 +961,29 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +/* HT */ +int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, + struct ieee80211_ht_info *ht_info); +int ieee80211_ht_addt_info_ie_to_ht_bss_info( + struct ieee80211_ht_addt_info *ht_add_info_ie, + struct ieee80211_ht_bss_info *bss_info); +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); + +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, + u16 tid, u16 initiator, u16 reason); +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); +void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct ieee80211_mgmt *mgmt, size_t len); +void ieee80211_process_addba_resp(struct ieee80211_local *local, + struct sta_info *sta, + struct ieee80211_mgmt *mgmt, + size_t len); +void ieee80211_process_addba_request(struct ieee80211_local *local, + struct sta_info *sta, + struct ieee80211_mgmt *mgmt, + size_t len); + /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ extern const unsigned char rfc1042_header[6]; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c22dcd605e48..25f90f7ccf3e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -445,52 +445,6 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, - u8 dialog_token, u16 status, u16 policy, - u16 buf_size, u16 timeout) -{ - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u16 capab; - - skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); - - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer " - "for addba resp frame\n", sdata->dev->name); - return; - } - - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); - else - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); - mgmt->u.action.category = WLAN_CATEGORY_BACK; - mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; - mgmt->u.action.u.addba_resp.dialog_token = dialog_token; - - capab = (u16)(policy << 1); /* bit 1 aggregation policy */ - capab |= (u16)(tid << 2); /* bit 5:2 TID number */ - capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ - - mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); - mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); - mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - - ieee80211_sta_tx(sdata, skb, 0); -} - static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, struct ieee80211_msrment_ie *request_ie, const u8 *da, const u8 *bssid, @@ -1057,278 +1011,6 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, elems.challenge_len + 2, 1); } -/* - * After accepting the AddBA Request we activated a timer, - * resetting it after each frame that arrives from the originator. - * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. - */ -static void sta_rx_agg_session_timer_expired(unsigned long data) -{ - /* not an elegant detour, but there is no choice as the timer passes - * only one argument, and various sta_info are needed here, so init - * flow in sta_info_create gives the TID as data, while the timer_to_id - * array gives the sta through container_of */ - u8 *ptid = (u8 *)data; - u8 *timer_to_id = ptid - *ptid; - struct sta_info *sta = container_of(timer_to_id, struct sta_info, - timer_to_tid[0]); - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); -#endif - ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, - (u16)*ptid, WLAN_BACK_TIMER, - WLAN_REASON_QSTA_TIMEOUT); -} - -static void ieee80211_sta_process_addba_request(struct ieee80211_local *local, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - struct ieee80211_hw *hw = &local->hw; - struct ieee80211_conf *conf = &hw->conf; - struct sta_info *sta; - struct tid_ampdu_rx *tid_agg_rx; - u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; - u8 dialog_token; - int ret = -EOPNOTSUPP; - DECLARE_MAC_BUF(mac); - - rcu_read_lock(); - - sta = sta_info_get(local, mgmt->sa); - if (!sta) { - rcu_read_unlock(); - return; - } - - /* extract session parameters from addba request frame */ - dialog_token = mgmt->u.action.u.addba_req.dialog_token; - timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); - start_seq_num = - le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; - - capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); - ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; - - status = WLAN_STATUS_REQUEST_DECLINED; - - /* sanity check for incoming parameters: - * check if configuration can support the BA policy - * and if buffer size does not exceeds max value */ - if (((ba_policy != 1) - && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) - || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { - status = WLAN_STATUS_INVALID_QOS_PARAM; -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "AddBA Req with bad params from " - "%s on tid %u. policy %d, buffer size %d\n", - print_mac(mac, mgmt->sa), tid, ba_policy, - buf_size); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - goto end_no_lock; - } - /* determine default buffer size */ - if (buf_size == 0) { - struct ieee80211_supported_band *sband; - - sband = local->hw.wiphy->bands[conf->channel->band]; - buf_size = IEEE80211_MIN_AMPDU_BUF; - buf_size = buf_size << sband->ht_info.ampdu_factor; - } - - - /* examine state machine */ - spin_lock_bh(&sta->lock); - - if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "unexpected AddBA Req from " - "%s on tid %u\n", - print_mac(mac, mgmt->sa), tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - goto end; - } - - /* prepare A-MPDU MLME for Rx aggregation */ - sta->ampdu_mlme.tid_rx[tid] = - kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); - if (!sta->ampdu_mlme.tid_rx[tid]) { -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_ERR "allocate rx mlme to tid %d failed\n", - tid); -#endif - goto end; - } - /* rx timer */ - sta->ampdu_mlme.tid_rx[tid]->session_timer.function = - sta_rx_agg_session_timer_expired; - sta->ampdu_mlme.tid_rx[tid]->session_timer.data = - (unsigned long)&sta->timer_to_tid[tid]; - init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); - - tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; - - /* prepare reordering buffer */ - tid_agg_rx->reorder_buf = - kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); - if (!tid_agg_rx->reorder_buf) { -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_ERR "can not allocate reordering buffer " - "to tid %d\n", tid); -#endif - kfree(sta->ampdu_mlme.tid_rx[tid]); - goto end; - } - memset(tid_agg_rx->reorder_buf, 0, - buf_size * sizeof(struct sk_buff *)); - - if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, - sta->addr, tid, &start_seq_num); -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - - if (ret) { - kfree(tid_agg_rx->reorder_buf); - kfree(tid_agg_rx); - sta->ampdu_mlme.tid_rx[tid] = NULL; - goto end; - } - - /* change state and send addba resp */ - sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; - tid_agg_rx->dialog_token = dialog_token; - tid_agg_rx->ssn = start_seq_num; - tid_agg_rx->head_seq_num = start_seq_num; - tid_agg_rx->buf_size = buf_size; - tid_agg_rx->timeout = timeout; - tid_agg_rx->stored_mpdu_num = 0; - status = WLAN_STATUS_SUCCESS; -end: - spin_unlock_bh(&sta->lock); - -end_no_lock: - ieee80211_send_addba_resp(sta->sdata, sta->addr, tid, - dialog_token, status, 1, buf_size, timeout); - rcu_read_unlock(); -} - -static void ieee80211_sta_process_addba_resp(struct ieee80211_local *local, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - struct ieee80211_hw *hw = &local->hw; - struct sta_info *sta; - u16 capab; - u16 tid; - u8 *state; - - rcu_read_lock(); - - sta = sta_info_get(local, mgmt->sa); - if (!sta) { - rcu_read_unlock(); - return; - } - - capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - - state = &sta->ampdu_mlme.tid_state_tx[tid]; - - spin_lock_bh(&sta->lock); - - if (!(*state & HT_ADDBA_REQUESTED_MSK)) { - spin_unlock_bh(&sta->lock); - goto addba_resp_exit; - } - - if (mgmt->u.action.u.addba_resp.dialog_token != - sta->ampdu_mlme.tid_tx[tid]->dialog_token) { - spin_unlock_bh(&sta->lock); -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - goto addba_resp_exit; - } - - del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) - == WLAN_STATUS_SUCCESS) { - *state |= HT_ADDBA_RECEIVED_MSK; - sta->ampdu_mlme.addba_req_num[tid] = 0; - - if (*state == HT_AGG_STATE_OPERATIONAL) - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); - - spin_unlock_bh(&sta->lock); - } else { - sta->ampdu_mlme.addba_req_num[tid]++; - /* this will allow the state check in stop_BA_session */ - *state = HT_AGG_STATE_OPERATIONAL; - spin_unlock_bh(&sta->lock); - ieee80211_stop_tx_ba_session(hw, sta->addr, tid, - WLAN_BACK_INITIATOR); - } - -addba_resp_exit: - rcu_read_unlock(); -} - -static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - u16 tid, params; - u16 initiator; - DECLARE_MAC_BUF(mac); - - rcu_read_lock(); - - sta = sta_info_get(local, mgmt->sa); - if (!sta) { - rcu_read_unlock(); - return; - } - - params = le16_to_cpu(mgmt->u.action.u.delba.params); - tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; - initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11; - -#ifdef CONFIG_MAC80211_HT_DEBUG - if (net_ratelimit()) - printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", - print_mac(mac, mgmt->sa), - initiator ? "initiator" : "recipient", tid, - mgmt->u.action.u.delba.reason_code); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - - if (initiator == WLAN_BACK_INITIATOR) - ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid, - WLAN_BACK_INITIATOR, 0); - else { /* WLAN_BACK_RECIPIENT */ - spin_lock_bh(&sta->lock); - sta->ampdu_mlme.tid_state_tx[tid] = - HT_AGG_STATE_OPERATIONAL; - spin_unlock_bh(&sta->lock); - ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, - WLAN_BACK_RECIPIENT); - } - rcu_read_unlock(); -} - static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) @@ -2207,28 +1889,6 @@ static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, break; } break; - case WLAN_CATEGORY_BACK: - switch (mgmt->u.action.u.addba_req.action_code) { - case WLAN_ACTION_ADDBA_REQ: - if (len < (IEEE80211_MIN_ACTION_SIZE + - sizeof(mgmt->u.action.u.addba_req))) - break; - ieee80211_sta_process_addba_request(local, mgmt, len); - break; - case WLAN_ACTION_ADDBA_RESP: - if (len < (IEEE80211_MIN_ACTION_SIZE + - sizeof(mgmt->u.action.u.addba_resp))) - break; - ieee80211_sta_process_addba_resp(local, mgmt, len); - break; - case WLAN_ACTION_DELBA: - if (len < (IEEE80211_MIN_ACTION_SIZE + - sizeof(mgmt->u.action.u.delba))) - break; - ieee80211_sta_process_delba(sdata, mgmt, len); - break; - } - break; case PLINK_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_rx_plink_frame(sdata, mgmt, len, rx_status); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7e09b30dd393..71cce0bcc5be 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1510,6 +1510,65 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) return RX_CONTINUE; } +static ieee80211_rx_result debug_noinline +ieee80211_rx_h_action(struct ieee80211_rx_data *rx) +{ + struct ieee80211_local *local = rx->local; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + int len = rx->skb->len; + + if (!ieee80211_is_action(mgmt->frame_control)) + return RX_CONTINUE; + + if (!rx->sta) + return RX_DROP_MONITOR; + + if (!(rx->flags & IEEE80211_RX_RA_MATCH)) + return RX_DROP_MONITOR; + + /* all categories we currently handle have action_code */ + if (len < IEEE80211_MIN_ACTION_SIZE + 1) + return RX_DROP_MONITOR; + + /* + * FIXME: revisit this, I'm sure we should handle most + * of these frames in other modes as well! + */ + if (sdata->vif.type != IEEE80211_IF_TYPE_STA && + sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + return RX_DROP_MONITOR; + + switch (mgmt->u.action.category) { + case WLAN_CATEGORY_BACK: + switch (mgmt->u.action.u.addba_req.action_code) { + case WLAN_ACTION_ADDBA_REQ: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.addba_req))) + return RX_DROP_MONITOR; + ieee80211_process_addba_request(local, rx->sta, mgmt, len); + break; + case WLAN_ACTION_ADDBA_RESP: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.addba_resp))) + return RX_DROP_MONITOR; + ieee80211_process_addba_resp(local, rx->sta, mgmt, len); + break; + case WLAN_ACTION_DELBA: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.delba))) + return RX_DROP_MONITOR; + ieee80211_process_delba(sdata, rx->sta, mgmt, len); + break; + } + rx->sta->rx_packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; + } + + return RX_CONTINUE; +} + static ieee80211_rx_result debug_noinline ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) { @@ -1689,6 +1748,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, CALL_RXH(ieee80211_rx_h_mesh_fwding); CALL_RXH(ieee80211_rx_h_data) CALL_RXH(ieee80211_rx_h_ctrl) + CALL_RXH(ieee80211_rx_h_action) CALL_RXH(ieee80211_rx_h_mgmt) #undef CALL_RXH -- cgit v1.2.3 From 39192c0bcf556c8521dcf0203714e9d48ac0b9f6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 14:49:03 +0200 Subject: mac80211: move spectrum management code out Like the HT code, this doesn't depend on the STA-mode implementation and can be handled entirely independently. There's only stub code for now, but when it gets filled having it in its own file will be beneficial. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Makefile | 1 + net/mac80211/ieee80211_i.h | 5 +++ net/mac80211/mlme.c | 89 +++------------------------------------------- net/mac80211/rx.c | 22 +++++++++--- net/mac80211/spectmgmt.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 89 deletions(-) create mode 100644 net/mac80211/spectmgmt.c (limited to 'net/mac80211') diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 1a7ac50910c3..2dc8f2bff27b 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -17,6 +17,7 @@ mac80211-y := \ aes_ccm.o \ cfg.o \ rx.o \ + spectmgmt.o \ tx.o \ key.o \ util.o \ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 60ec7ad27643..b2ca9e6122c6 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -984,6 +984,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len); +/* Spectrum management */ +void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len); + /* utility functions/constants */ extern void *mac80211_wiphy_privid; /* for wiphy privid */ extern const unsigned char rfc1042_header[6]; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 25f90f7ccf3e..f1ee9d22cf4b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -445,53 +445,6 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, - struct ieee80211_msrment_ie *request_ie, - const u8 *da, const u8 *bssid, - u8 dialog_token) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *msr_report; - - skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + - sizeof(struct ieee80211_msrment_ie)); - - if (!skb) { - printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", sdata->dev->name); - return; - } - - skb_reserve(skb, local->hw.extra_tx_headroom); - msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); - memset(msr_report, 0, 24); - memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(msr_report->bssid, bssid, ETH_ALEN); - msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); - msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; - msr_report->u.action.u.measurement.action_code = - WLAN_ACTION_SPCT_MSR_RPRT; - msr_report->u.action.u.measurement.dialog_token = dialog_token; - - msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; - msr_report->u.action.u.measurement.length = - sizeof(struct ieee80211_msrment_ie); - - memset(&msr_report->u.action.u.measurement.msr_elem, 0, - sizeof(struct ieee80211_msrment_ie)); - msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; - msr_report->u.action.u.measurement.msr_elem.mode |= - IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; - msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - - ieee80211_sta_tx(sdata, skb, 0); -} - /* MLME */ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss) @@ -1011,24 +964,6 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, elems.challenge_len + 2, 1); } -static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - /* - * Ignoring measurement request is spec violation. - * Mandatory measurements must be reported optional - * measurements might be refused or reported incapable - * For now just refuse - * TODO: Answer basic measurement as unmeasured - */ - ieee80211_send_refuse_measurement_request(sdata, - &mgmt->u.action.u.measurement.msr_elem, - mgmt->sa, mgmt->bssid, - mgmt->u.action.u.measurement.dialog_token); -} - - static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, @@ -1870,32 +1805,16 @@ static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = sdata->local; - - /* all categories we currently handle have action_code */ - if (len < IEEE80211_MIN_ACTION_SIZE + 1) + /* currently we only handle mesh interface action frames here */ + if (!ieee80211_vif_is_mesh(&sdata->vif)) return; switch (mgmt->u.action.category) { - case WLAN_CATEGORY_SPECTRUM_MGMT: - if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) - break; - switch (mgmt->u.action.u.measurement.action_code) { - case WLAN_ACTION_SPCT_MSR_REQ: - if (len < (IEEE80211_MIN_ACTION_SIZE + - sizeof(mgmt->u.action.u.measurement))) - break; - ieee80211_sta_process_measurement_req(sdata, mgmt, len); - break; - } - break; case PLINK_CATEGORY: - if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_plink_frame(sdata, mgmt, len, rx_status); + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); break; case MESH_PATH_SEL_CATEGORY: - if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_path_sel_frame(sdata, mgmt, len); + mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 71cce0bcc5be..d00ace78bf8d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1561,12 +1561,26 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ieee80211_process_delba(sdata, rx->sta, mgmt, len); break; } - rx->sta->rx_packets++; - dev_kfree_skb(rx->skb); - return RX_QUEUED; + break; + case WLAN_CATEGORY_SPECTRUM_MGMT: + if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) + return RX_DROP_MONITOR; + switch (mgmt->u.action.u.measurement.action_code) { + case WLAN_ACTION_SPCT_MSR_REQ: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.measurement))) + return RX_DROP_MONITOR; + ieee80211_process_measurement_req(sdata, mgmt, len); + break; + } + break; + default: + return RX_CONTINUE; } - return RX_CONTINUE; + rx->sta->rx_packets++; + dev_kfree_skb(rx->skb); + return RX_QUEUED; } static ieee80211_rx_result debug_noinline diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c new file mode 100644 index 000000000000..b7129f4ae0c3 --- /dev/null +++ b/net/mac80211/spectmgmt.c @@ -0,0 +1,86 @@ +/* + * spectrum management + * + * Copyright 2003, Jouni Malinen + * Copyright 2002-2005, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright 2006-2007 Jiri Benc + * Copyright 2007, Michael Wu + * Copyright 2007-2008, Intel Corporation + * Copyright 2008, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include "ieee80211_i.h" +#include "sta_info.h" +#include "wme.h" + +static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, + struct ieee80211_msrment_ie *request_ie, + const u8 *da, const u8 *bssid, + u8 dialog_token) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *msr_report; + + skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + + sizeof(struct ieee80211_msrment_ie)); + + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer for " + "measurement report frame\n", sdata->dev->name); + return; + } + + skb_reserve(skb, local->hw.extra_tx_headroom); + msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); + memset(msr_report, 0, 24); + memcpy(msr_report->da, da, ETH_ALEN); + memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(msr_report->bssid, bssid, ETH_ALEN); + msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + + skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); + msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; + msr_report->u.action.u.measurement.action_code = + WLAN_ACTION_SPCT_MSR_RPRT; + msr_report->u.action.u.measurement.dialog_token = dialog_token; + + msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; + msr_report->u.action.u.measurement.length = + sizeof(struct ieee80211_msrment_ie); + + memset(&msr_report->u.action.u.measurement.msr_elem, 0, + sizeof(struct ieee80211_msrment_ie)); + msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; + msr_report->u.action.u.measurement.msr_elem.mode |= + IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; + msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; + + ieee80211_sta_tx(sdata, skb, 0); +} + +void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len) +{ + /* + * Ignoring measurement request is spec violation. + * Mandatory measurements must be reported optional + * measurements might be refused or reported incapable + * For now just refuse + * TODO: Answer basic measurement as unmeasured + */ + ieee80211_send_refuse_measurement_request(sdata, + &mgmt->u.action.u.measurement.msr_elem, + mgmt->sa, mgmt->bssid, + mgmt->u.action.u.measurement.dialog_token); +} -- cgit v1.2.3 From 759ef3eb1eeba8ff7411771e7b9cf6bfd6bb9cfe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 14:55:09 +0200 Subject: mac80211: make ieee80211_rx_h_mgmt more readable That function isn't exactly easy to read especially since it does something in an if branch that continues after the if because the else returns. Express it in a more readable way. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d00ace78bf8d..d0803797902b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1586,20 +1586,20 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) static ieee80211_rx_result debug_noinline ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; - sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); - if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS || - sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) && - !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) - ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); - else + if (sdata->vif.type != IEEE80211_IF_TYPE_STA && + sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + return RX_DROP_MONITOR; + + if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) return RX_DROP_MONITOR; + ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); return RX_QUEUED; } -- cgit v1.2.3 From e50db65c0dad109aae77c353305853b31555b228 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Sep 2008 15:07:09 +0200 Subject: mac80211: move frame TX function The ieee80211_sta_tx function isn't MLME code any more, it's getting used by a lot of code. Move it to utils and rename it to ieee80211_tx_skb. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ht.c | 8 ++++---- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/mesh_hwmp.c | 4 ++-- net/mac80211/mesh_plink.c | 2 +- net/mac80211/mlme.c | 24 +++++------------------- net/mac80211/scan.c | 2 +- net/mac80211/spectmgmt.c | 2 +- net/mac80211/util.c | 14 ++++++++++++++ 8 files changed, 30 insertions(+), 30 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 7e93e1079ade..4dc35c9dabc7 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -113,7 +113,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(start_seq_num << 4); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, @@ -159,7 +159,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, @@ -202,7 +202,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, mgmt->u.action.u.delba.params = cpu_to_le16(params); mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) @@ -231,7 +231,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 bar->control = cpu_to_le16(bar_control); bar->start_seq_num = cpu_to_le16(ssn); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b2ca9e6122c6..6f334e4c3d66 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -912,8 +912,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); u64 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); -void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - int encrypt); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); void ieee802_11_parse_elems(u8 *start, size_t len, @@ -1000,6 +998,8 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr); void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); +void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + int encrypt); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 59fd7fe377e0..210d6b852406 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); return 0; } @@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); return 0; } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 74983cfa7293..7356462dee96 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -217,7 +217,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, memcpy(pos, &reason, 2); } - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); return 0; } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f1ee9d22cf4b..2c06f6965b7d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -96,20 +96,6 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, } /* frame sending functions */ -void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - int encrypt) -{ - skb->dev = sdata->local->mdev; - skb_set_mac_header(skb, 0); - skb_set_network_header(skb, 0); - skb_set_transport_header(skb, 0); - - skb->iif = sdata->dev->ifindex; - skb->do_not_encrypt = !encrypt; - - dev_queue_xmit(skb); -} - static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int transaction, u8 *extra, size_t extra_len, @@ -144,7 +130,7 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, if (extra) memcpy(skb_put(skb, extra_len), extra, extra_len); - ieee80211_sta_tx(sdata, skb, encrypt); + ieee80211_tx_skb(sdata, skb, encrypt); } void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, @@ -204,7 +190,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, *pos = rate->bitrate / 5; } - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, @@ -412,7 +398,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, if (ifsta->assocreq_ies) memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } @@ -442,7 +428,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* u.deauth.reason_code == u.disassoc.reason_code */ mgmt->u.deauth.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } /* MLME */ @@ -1796,7 +1782,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", sdata->dev->name, print_mac(mac, resp->da)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 9f6120150120..010781b806f3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -421,7 +421,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index b7129f4ae0c3..f72bad636d8e 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -65,7 +65,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - ieee80211_sta_tx(sdata, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); } void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 55be3ef5c755..c3a22ab2ad2e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -598,3 +598,17 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) for (i = 0; i < local_to_hw(local)->queues; i++) local->ops->conf_tx(local_to_hw(local), i, &qparam); } + +void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + int encrypt) +{ + skb->dev = sdata->local->mdev; + skb_set_mac_header(skb, 0); + skb_set_network_header(skb, 0); + skb_set_transport_header(skb, 0); + + skb->iif = sdata->dev->ifindex; + skb->do_not_encrypt = !encrypt; + + dev_queue_xmit(skb); +} -- cgit v1.2.3 From aee14ceb5230afb5c17a4e28222ab9734ffd5002 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Sep 2008 16:33:15 +0200 Subject: mac80211: Reorder debugfs calls during netdev deinit ieee80211_free_keys() must be called before ieee80211_debugfs_remove_netdev() in order to make sure that the possible default_key symlink is removed before attempting to remove the netdev debugfs directory. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 4a623b8e91fd..672cec60a2fb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -31,11 +31,11 @@ static void ieee80211_teardown_sdata(struct net_device *dev) int flushed; int i; - ieee80211_debugfs_remove_netdev(sdata); - /* free extra data */ ieee80211_free_keys(sdata); + ieee80211_debugfs_remove_netdev(sdata); + for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) __skb_queue_purge(&sdata->fragments[i].skb_list); sdata->fragment_next = 0; -- cgit v1.2.3 From b2e1b30290539b344cbaff0d9da38012e03aa347 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 9 Sep 2008 23:19:48 -0700 Subject: cfg80211: Add new wireless regulatory infrastructure This adds the new wireless regulatory infrastructure. The main motiviation behind this was to centralize regulatory code as each driver was implementing their own regulatory solution, and to replace the initial centralized code we have where: * only 3 regulatory domains are supported: US, JP and EU * regulatory domains can only be changed through module parameter * all rules were built statically in the kernel We now have support for regulatory domains for many countries and regulatory domains are now queried through a userspace agent through udev allowing distributions to update regulatory rules without updating the kernel. Each driver can regulatory_hint() a regulatory domain based on either their EEPROM mapped regulatory domain value to a respective ISO/IEC 3166-1 country code or pass an internally built regulatory domain. We also add support to let the user set the regulatory domain through userspace in case of faulty EEPROMs to further help compliance. Support for world roaming will be added soon for cards capable of this. For more information see: http://wireless.kernel.org/en/developers/Regulatory/CRDA For now we leave an option to enable the old module parameter, ieee80211_regdom, and to build the 3 old regdomains statically (US, JP and EU). This option is CONFIG_WIRELESS_OLD_REGULATORY. These old static definitions and the module parameter is being scheduled for removal for 2.6.29. Note that if you use this you won't make use of a world regulatory domain as its pointless. If you leave this option enabled and if CRDA is present and you use US or JP we will try to ask CRDA to update us a regulatory domain for us. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 18 + Documentation/networking/regulatory.txt | 194 +++++++ include/linux/nl80211.h | 96 +++- include/net/cfg80211.h | 60 +++ include/net/mac80211.h | 2 + include/net/wireless.h | 58 +++ net/mac80211/cfg.c | 7 + net/wireless/Kconfig | 32 ++ net/wireless/core.c | 162 +++++- net/wireless/core.h | 2 +- net/wireless/nl80211.c | 151 ++++++ net/wireless/reg.c | 805 +++++++++++++++++++++++++---- net/wireless/reg.h | 44 ++ 13 files changed, 1513 insertions(+), 118 deletions(-) create mode 100644 Documentation/networking/regulatory.txt create mode 100644 net/wireless/reg.h (limited to 'net/mac80211') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index eb1a47b97427..c93fcdec246d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -6,6 +6,24 @@ be removed from this file. --------------------------- +What: old static regulatory information and ieee80211_regdom module parameter +When: 2.6.29 +Why: The old regulatory infrastructure has been replaced with a new one + which does not require statically defined regulatory domains. We do + not want to keep static regulatory domains in the kernel due to the + the dynamic nature of regulatory law and localization. We kept around + the old static definitions for the regulatory domains of: + * US + * JP + * EU + and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was + set. We also kept around the ieee80211_regdom module parameter in case + some applications were relying on it. Changing regulatory domains + can now be done instead by using nl80211, as is done with iw. +Who: Luis R. Rodriguez + +--------------------------- + What: dev->power.power_state When: July 2007 Why: Broken design for runtime control over driver power states, confusing diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt new file mode 100644 index 000000000000..a96989a8ff35 --- /dev/null +++ b/Documentation/networking/regulatory.txt @@ -0,0 +1,194 @@ +Linux wireless regulatory documentation +--------------------------------------- + +This document gives a brief review over how the Linux wireless +regulatory infrastructure works. + +More up to date information can be obtained at the project's web page: + +http://wireless.kernel.org/en/developers/Regulatory + +Keeping regulatory domains in userspace +--------------------------------------- + +Due to the dynamic nature of regulatory domains we keep them +in userspace and provide a framework for userspace to upload +to the kernel one regulatory domain to be used as the central +core regulatory domain all wireless devices should adhere to. + +How to get regulatory domains to the kernel +------------------------------------------- + +Userspace gets a regulatory domain in the kernel by having +a userspace agent build it and send it via nl80211. Only +expected regulatory domains will be respected by the kernel. + +A currently available userspace agent which can accomplish this +is CRDA - central regulatory domain agent. Its documented here: + +http://wireless.kernel.org/en/developers/Regulatory/CRDA + +Essentially the kernel will send a udev event when it knows +it needs a new regulatory domain. A udev rule can be put in place +to trigger crda to send the respective regulatory domain for a +specific ISO/IEC 3166 alpha2. + +Below is an example udev rule which can be used: + +# Example file, should be put in /etc/udev/rules.d/regulatory.rules +KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda" + +The alpha2 is passed as an environment variable under the variable COUNTRY. + +Who asks for regulatory domains? +-------------------------------- + +* Users + +Users can use iw: + +http://wireless.kernel.org/en/users/Documentation/iw + +An example: + + # set regulatory domain to "Costa Rica" + iw reg set CR + +This will request the kernel to set the regulatory domain to +the specificied alpha2. The kernel in turn will then ask userspace +to provide a regulatory domain for the alpha2 specified by the user +by sending a uevent. + +* Wireless subsystems for Country Information elements + +The kernel will send a uevent to inform userspace a new +regulatory domain is required. More on this to be added +as its integration is added. + +* Drivers + +If drivers determine they need a specific regulatory domain +set they can inform the wireless core using regulatory_hint(). +They have two options -- they either provide an alpha2 so that +crda can provide back a regulatory domain for that country or +they can build their own regulatory domain based on internal +custom knowledge so the wireless core can respect it. + +*Most* drivers will rely on the first mechanism of providing a +regulatory hint with an alpha2. For these drivers there is an additional +check that can be used to ensure compliance based on custom EEPROM +regulatory data. This additional check can be used by drivers by +registering on its struct wiphy a reg_notifier() callback. This notifier +is called when the core's regulatory domain has been changed. The driver +can use this to review the changes made and also review who made them +(driver, user, country IE) and determine what to allow based on its +internal EEPROM data. Devices drivers wishing to be capable of world +roaming should use this callback. More on world roaming will be +added to this document when its support is enabled. + +Device drivers who provide their own built regulatory domain +do not need a callback as the channels registered by them are +the only ones that will be allowed and therefore *additional* +cannels cannot be enabled. + +Example code - drivers hinting an alpha2: +------------------------------------------ + +This example comes from the zd1211rw device driver. You can start +by having a mapping of your device's EEPROM country/regulatory +domain value to to a specific alpha2 as follows: + +static struct zd_reg_alpha2_map reg_alpha2_map[] = { + { ZD_REGDOMAIN_FCC, "US" }, + { ZD_REGDOMAIN_IC, "CA" }, + { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ + { ZD_REGDOMAIN_JAPAN, "JP" }, + { ZD_REGDOMAIN_JAPAN_ADD, "JP" }, + { ZD_REGDOMAIN_SPAIN, "ES" }, + { ZD_REGDOMAIN_FRANCE, "FR" }, + +Then you can define a routine to map your read EEPROM value to an alpha2, +as follows: + +static int zd_reg2alpha2(u8 regdomain, char *alpha2) +{ + unsigned int i; + struct zd_reg_alpha2_map *reg_map; + for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) { + reg_map = ®_alpha2_map[i]; + if (regdomain == reg_map->reg) { + alpha2[0] = reg_map->alpha2[0]; + alpha2[1] = reg_map->alpha2[1]; + return 0; + } + } + return 1; +} + +Lastly, you can then hint to the core of your discovered alpha2, if a match +was found. You need to do this after you have registered your wiphy. You +are expected to do this during initialization. + + r = zd_reg2alpha2(mac->regdomain, alpha2); + if (!r) + regulatory_hint(hw->wiphy, alpha2, NULL); + +Example code - drivers providing a built in regulatory domain: +-------------------------------------------------------------- + +If you have regulatory information you can obtain from your +driver and you *need* to use this we let you build a regulatory domain +structure and pass it to the wireless core. To do this you should +kmalloc() a structure big enough to hold your regulatory domain +structure and you should then fill it with your data. Finally you simply +call regulatory_hint() with the regulatory domain structure in it. + +Bellow is a simple example, with a regulatory domain cached using the stack. +Your implementation may vary (read EEPROM cache instead, for example). + +Example cache of some regulatory domain + +struct ieee80211_regdomain mydriver_jp_regdom = { + .n_reg_rules = 3, + .alpha2 = "JP", + //.alpha2 = "99", /* If I have no alpha2 to map it to */ + .reg_rules = { + /* IEEE 802.11b/g, channels 1..14 */ + REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), + /* IEEE 802.11a, channels 34..48 */ + REG_RULE(5170-20, 5240+20, 40, 6, 20, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channels 52..64 */ + REG_RULE(5260-20, 5320+20, 40, 6, 20, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + } +}; + +Then in some part of your code after your wiphy has been registered: + + int r; + struct ieee80211_regdomain *rd; + int size_of_regd; + int num_rules = mydriver_jp_regdom.n_reg_rules; + unsigned int i; + + size_of_regd = sizeof(struct ieee80211_regdomain) + + (num_rules * sizeof(struct ieee80211_reg_rule)); + + rd = kzalloc(size_of_regd, GFP_KERNEL); + if (!rd) + return -ENOMEM; + + memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain)); + + for (i=0; i < num_rules; i++) { + memcpy(&rd->reg_rules[i], &mydriver_jp_regdom.reg_rules[i], + sizeof(struct ieee80211_reg_rule)); + } + r = regulatory_hint(hw->wiphy, NULL, rd); + if (r) { + kfree(rd); + return r; + } + diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 5e51f4e7600b..9bad65400fba 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -92,6 +92,20 @@ * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by * %NL80211_ATTR_IFINDEX. * + * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command + * after being queried by the kernel. CRDA replies by sending a regulatory + * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our + * current alpha2 if it found a match. It also provides + * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each + * regulatory rule is a nested set of attributes given by + * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and + * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by + * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and + * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. + * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain + * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will + * store this as a valid request and then query userspace for it. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -131,7 +145,10 @@ enum nl80211_commands { NL80211_CMD_SET_BSS, - /* add commands here */ + NL80211_CMD_SET_REG, + NL80211_CMD_REQ_SET_REG, + + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ __NL80211_CMD_AFTER_LAST, @@ -197,10 +214,21 @@ enum nl80211_commands { * info given for %NL80211_CMD_GET_MPATH, nested attribute described at * &enum nl80211_mpath_info. * - * * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of * &enum nl80211_mntr_flags. * + * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the + * current regulatory domain should be set to or is already set to. + * For example, 'CR', for Costa Rica. This attribute is used by the kernel + * to query the CRDA to retrieve one regulatory domain. This attribute can + * also be used by userspace to query the kernel for the currently set + * regulatory domain. We chose an alpha2 as that is also used by the + * IEEE-802.11d country information element to identify a country. + * Users can also simply ask the wireless core to set regulatory domain + * to a specific alpha2. + * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory + * rules. + * * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled * (u8, 0 or 1) @@ -265,6 +293,9 @@ enum nl80211_attrs { NL80211_ATTR_SUPPORTED_IFTYPES, + NL80211_ATTR_REG_ALPHA2, + NL80211_ATTR_REG_RULES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -278,6 +309,7 @@ enum nl80211_attrs { #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY #define NL80211_MAX_SUPP_RATES 32 +#define NL80211_MAX_SUPP_REG_RULES 32 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 @@ -472,6 +504,66 @@ enum nl80211_bitrate_attr { NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 }; +/** + * enum nl80211_reg_rule_attr - regulatory rule attributes + * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional + * considerations for a given frequency range. These are the + * &enum nl80211_reg_rule_flags. + * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory + * rule in KHz. This is not a center of frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule + * in KHz. This is not a center a frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this + * frequency range, in KHz. + * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain + * for a given frequency range. The value is in mBi (100 * dBi). + * If you don't have one then don't send this. + * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for + * a given frequency range. The value is in mBm (100 * dBm). + */ +enum nl80211_reg_rule_attr { + __NL80211_REG_RULE_ATTR_INVALID, + NL80211_ATTR_REG_RULE_FLAGS, + + NL80211_ATTR_FREQ_RANGE_START, + NL80211_ATTR_FREQ_RANGE_END, + NL80211_ATTR_FREQ_RANGE_MAX_BW, + + NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, + NL80211_ATTR_POWER_RULE_MAX_EIRP, + + /* keep last */ + __NL80211_REG_RULE_ATTR_AFTER_LAST, + NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_NO_CCK: CCK modulation not allowed + * @NL80211_RRF_NO_INDOOR: indoor operation not allowed + * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed + * @NL80211_RRF_DFS: DFS support is required to be used + * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links + * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links + * @NL80211_RRF_PASSIVE_SCAN: passive scan is required + * @NL80211_RRF_NO_IBSS: no IBSS is allowed + */ +enum nl80211_reg_rule_flags { + NL80211_RRF_NO_OFDM = 1<<0, + NL80211_RRF_NO_CCK = 1<<1, + NL80211_RRF_NO_INDOOR = 1<<2, + NL80211_RRF_NO_OUTDOOR = 1<<3, + NL80211_RRF_DFS = 1<<4, + NL80211_RRF_PTP_ONLY = 1<<5, + NL80211_RRF_PTMP_ONLY = 1<<6, + NL80211_RRF_PASSIVE_SCAN = 1<<7, + NL80211_RRF_NO_IBSS = 1<<8, +}; + /** * enum nl80211_mntr_flags - monitor configuration flags * diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0a72d1e3d3ab..9f40c4d417d7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -287,6 +287,66 @@ struct bss_parameters { int use_short_slot_time; }; +/** + * enum reg_set_by - Indicates who is trying to set the regulatory domain + * @REGDOM_SET_BY_INIT: regulatory domain was set by initialization. We will be + * using a static world regulatory domain by default. + * @REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world regulatory domain. + * @REGDOM_SET_BY_USER: User asked the wireless core to set the + * regulatory domain. + * @REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the wireless core + * it thinks its knows the regulatory domain we should be in. + * @REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an 802.11 country + * information element with regulatory information it thinks we + * should consider. + */ +enum reg_set_by { + REGDOM_SET_BY_INIT, + REGDOM_SET_BY_CORE, + REGDOM_SET_BY_USER, + REGDOM_SET_BY_DRIVER, + REGDOM_SET_BY_COUNTRY_IE, +}; + +struct ieee80211_freq_range { + u32 start_freq_khz; + u32 end_freq_khz; + u32 max_bandwidth_khz; +}; + +struct ieee80211_power_rule { + u32 max_antenna_gain; + u32 max_eirp; +}; + +struct ieee80211_reg_rule { + struct ieee80211_freq_range freq_range; + struct ieee80211_power_rule power_rule; + u32 flags; +}; + +struct ieee80211_regdomain { + u32 n_reg_rules; + char alpha2[2]; + struct ieee80211_reg_rule reg_rules[]; +}; + +#define MHZ_TO_KHZ(freq) (freq * 1000) +#define KHZ_TO_MHZ(freq) (freq / 1000) +#define DBI_TO_MBI(gain) (gain * 100) +#define MBI_TO_DBI(gain) (gain / 100) +#define DBM_TO_MBM(gain) (gain * 100) +#define MBM_TO_DBM(gain) (gain / 100) + +#define REG_RULE(start, end, bw, gain, eirp, reg_flags) { \ + .freq_range.start_freq_khz = (start) * 1000, \ + .freq_range.end_freq_khz = (end) * 1000, \ + .freq_range.max_bandwidth_khz = (bw) * 1000, \ + .power_rule.max_antenna_gain = (gain) * 100, \ + .power_rule.max_eirp = (eirp) * 100, \ + .flags = reg_flags, \ + } + /* from net/wireless.h */ struct wiphy; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index fb9e62211c34..f504e3eca7d3 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -833,6 +833,8 @@ struct ieee80211_hw { s8 max_signal; }; +struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); + /** * SET_IEEE80211_DEV - set device for 802.11 hardware * diff --git a/include/net/wireless.h b/include/net/wireless.h index 1dc8ec3daa2f..e4378cc6bf8e 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -60,6 +60,7 @@ enum ieee80211_channel_flags { * with cfg80211. * * @center_freq: center frequency in MHz + * @max_bandwidth: maximum allowed bandwidth for this channel, in MHz * @hw_value: hardware-specific value for the channel * @flags: channel flags from &enum ieee80211_channel_flags. * @orig_flags: channel flags at registration time, used by regulatory @@ -73,6 +74,7 @@ enum ieee80211_channel_flags { struct ieee80211_channel { enum ieee80211_band band; u16 center_freq; + u8 max_bandwidth; u16 hw_value; u32 flags; int max_antenna_gain; @@ -178,6 +180,7 @@ struct ieee80211_supported_band { * struct wiphy - wireless hardware description * @idx: the wiphy index assigned to this item * @class_dev: the class device representing /sys/class/ieee80211/ + * @reg_notifier: the driver's regulatory notification callback */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -197,6 +200,9 @@ struct wiphy { struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; + /* Lets us get back the wiphy on the callback */ + int (*reg_notifier)(struct wiphy *wiphy, enum reg_set_by setby); + /* fields below are read-only, assigned by cfg80211 */ /* the item in /sys/class/ieee80211/ points to this, @@ -322,6 +328,58 @@ extern int ieee80211_frequency_to_channel(int freq); */ extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy, int freq); +/** + * __regulatory_hint - hint to the wireless core a regulatory domain + * @wiphy: if a driver is providing the hint this is the driver's very + * own &struct wiphy + * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain + * should be in. If @rd is set this should be NULL + * @rd: a complete regulatory domain, if passed the caller need not worry + * about freeing it + * + * The Wireless subsystem can use this function to hint to the wireless core + * what it believes should be the current regulatory domain by + * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory + * domain should be in or by providing a completely build regulatory domain. + * + * Returns -EALREADY if *a regulatory domain* has already been set. Note that + * this could be by another driver. It is safe for drivers to continue if + * -EALREADY is returned, if drivers are not capable of world roaming they + * should not register more channels than they support. Right now we only + * support listening to the first driver hint. If the driver is capable + * of world roaming but wants to respect its own EEPROM mappings for + * specific regulatory domains it should register the @reg_notifier callback + * on the &struct wiphy. Returns 0 if the hint went through fine or through an + * intersection operation. Otherwise a standard error code is returned. + * + */ +extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, + const char *alpha2, struct ieee80211_regdomain *rd); +/** + * regulatory_hint - driver hint to the wireless core a regulatory domain + * @wiphy: the driver's very own &struct wiphy + * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain + * should be in. If @rd is set this should be NULL. Note that if you + * set this to NULL you should still set rd->alpha2 to some accepted + * alpha2. + * @rd: a complete regulatory domain provided by the driver. If passed + * the driver does not need to worry about freeing it. + * + * Wireless drivers can use this function to hint to the wireless core + * what it believes should be the current regulatory domain by + * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory + * domain should be in or by providing a completely build regulatory domain. + * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried + * for a regulatory domain structure for the respective country. If + * a regulatory domain is build and passed you should set the alpha2 + * if possible, otherwise set it to the special value of "99" which tells + * the wireless core it is unknown. If you pass a built regulatory domain + * and we return non zero you are in charge of kfree()'ing the structure. + * + * See __regulatory_hint() documentation for possible return values. + */ +extern int regulatory_hint(struct wiphy *wiphy, + const char *alpha2, struct ieee80211_regdomain *rd); /** * ieee80211_get_channel - get channel struct from wiphy for specified frequency diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 928813ce08e2..5a3bdaad6c19 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -17,6 +17,13 @@ #include "rate.h" #include "mesh.h" +struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + return &local->hw; +} +EXPORT_SYMBOL(wiphy_to_hw); + static enum ieee80211_if_types nl80211_type_to_mac80211_type(enum nl80211_iftype type) { diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 833b024f8f66..b97bd9fe6b79 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -14,6 +14,38 @@ config NL80211 If unsure, say Y. +config WIRELESS_OLD_REGULATORY + bool "Old wireless static regulatory defintions" + default n + ---help--- + This option enables the old static regulatory information + and uses it within the new framework. This is available + temporarily as an option to help prevent immediate issues + due to the switch to the new regulatory framework which + does require a new userspace application which has the + database of regulatory information (CRDA) and another for + setting regulatory domains (iw). + + For more information see: + + http://wireless.kernel.org/en/developers/Regulatory/CRDA + http://wireless.kernel.org/en/users/Documentation/iw + + It is important to note though that if you *do* have CRDA present + and if this option is enabled CRDA *will* be called to update the + regulatory domain (for US and JP only). Support for letting the user + set the regulatory domain through iw is also supported. This option + mainly exists to leave around for a kernel release some old static + regulatory domains that were defined and to keep around the old + ieee80211_regdom module parameter. This is being phased out and you + should stop using them ASAP. + + Say N unless you cannot install a new userspace application + or have one currently depending on the ieee80211_regdom module + parameter and cannot port it to use the new userspace interfaces. + + This is scheduled for removal for 2.6.29. + config WIRELESS_EXT bool "Wireless extensions" default n diff --git a/net/wireless/core.c b/net/wireless/core.c index 7e995ac06a0c..a910cd2d0fd1 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -13,12 +13,14 @@ #include #include #include +#include #include #include #include #include "nl80211.h" #include "core.h" #include "sysfs.h" +#include "reg.h" /* name for sysfs, %d is appended */ #define PHY_NAME "phy" @@ -27,6 +29,107 @@ MODULE_AUTHOR("Johannes Berg"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("wireless configuration support"); +struct list_head regulatory_requests; + +/* Central wireless core regulatory domains, we only need two, + * the current one and a world regulatory domain in case we have no + * information to give us an alpha2 */ +struct ieee80211_regdomain *cfg80211_regdomain; + +/* We keep a static world regulatory domain in case of the absence of CRDA */ +const struct ieee80211_regdomain world_regdom = { + .n_reg_rules = 1, + .alpha2 = "00", + .reg_rules = { + REG_RULE(2402, 2472, 40, 6, 20, + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS), + } +}; + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY +/* All this fucking static junk will be removed soon, so + * don't fucking count on it !@#$ */ + +static char *ieee80211_regdom = "US"; +module_param(ieee80211_regdom, charp, 0444); +MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); + +/* We assume 40 MHz bandwidth for the old regulatory work. + * We make emphasis we are using the exact same frequencies + * as before */ + +const struct ieee80211_regdomain us_regdom = { + .n_reg_rules = 6, + .alpha2 = "US", + .reg_rules = { + /* IEEE 802.11b/g, channels 1..11 */ + REG_RULE(2412-20, 2462+20, 40, 6, 27, 0), + /* IEEE 802.11a, channel 36 */ + REG_RULE(5180-20, 5180+20, 40, 6, 23, 0), + /* IEEE 802.11a, channel 40 */ + REG_RULE(5200-20, 5200+20, 40, 6, 23, 0), + /* IEEE 802.11a, channel 44 */ + REG_RULE(5220-20, 5220+20, 40, 6, 23, 0), + /* IEEE 802.11a, channels 48..64 */ + REG_RULE(5240-20, 5320+20, 40, 6, 23, 0), + /* IEEE 802.11a, channels 149..165, outdoor */ + REG_RULE(5745-20, 5825+20, 40, 6, 30, 0), + } +}; + +const struct ieee80211_regdomain jp_regdom = { + .n_reg_rules = 3, + .alpha2 = "JP", + .reg_rules = { + /* IEEE 802.11b/g, channels 1..14 */ + REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), + /* IEEE 802.11a, channels 34..48 */ + REG_RULE(5170-20, 5240+20, 40, 6, 20, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channels 52..64 */ + REG_RULE(5260-20, 5320+20, 40, 6, 20, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + } +}; + +const struct ieee80211_regdomain eu_regdom = { + .n_reg_rules = 6, + /* This alpha2 is bogus, we leave it here just for stupid + * backward compatibility */ + .alpha2 = "EU", + .reg_rules = { + /* IEEE 802.11b/g, channels 1..13 */ + REG_RULE(2412-20, 2472+20, 40, 6, 20, 0), + /* IEEE 802.11a, channel 36 */ + REG_RULE(5180-20, 5180+20, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channel 40 */ + REG_RULE(5200-20, 5200+20, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channel 44 */ + REG_RULE(5220-20, 5220+20, 40, 6, 23, + NL80211_RRF_PASSIVE_SCAN), + /* IEEE 802.11a, channels 48..64 */ + REG_RULE(5240-20, 5320+20, 40, 6, 20, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + /* IEEE 802.11a, channels 100..140 */ + REG_RULE(5500-20, 5700+20, 40, 6, 30, + NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + } +}; + +#endif + +struct ieee80211_regdomain *cfg80211_world_regdom = + (struct ieee80211_regdomain *) &world_regdom; + +LIST_HEAD(regulatory_requests); +DEFINE_MUTEX(cfg80211_reg_mutex); + /* RCU might be appropriate here since we usually * only read the list, and that can happen quite * often because we need to do it for each command */ @@ -302,7 +405,9 @@ int wiphy_register(struct wiphy *wiphy) ieee80211_set_bitrate_flags(wiphy); /* set up regulatory info */ - wiphy_update_regulatory(wiphy); + mutex_lock(&cfg80211_reg_mutex); + wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); + mutex_unlock(&cfg80211_reg_mutex); mutex_lock(&cfg80211_drv_mutex); @@ -409,9 +514,35 @@ static struct notifier_block cfg80211_netdev_notifier = { .notifier_call = cfg80211_netdev_notifier_call, }; +#ifdef CONFIG_WIRELESS_OLD_REGULATORY +const struct ieee80211_regdomain *static_regdom(char *alpha2) +{ + if (alpha2[0] == 'U' && alpha2[1] == 'S') + return &us_regdom; + if (alpha2[0] == 'J' && alpha2[1] == 'P') + return &jp_regdom; + if (alpha2[0] == 'E' && alpha2[1] == 'U') + return &eu_regdom; + /* Default, as per the old rules */ + return &us_regdom; +} +#endif + static int cfg80211_init(void) { - int err = wiphy_sysfs_init(); + int err; + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + cfg80211_regdomain = + (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); + /* Used during reset_regdomains_static() */ + cfg80211_world_regdom = cfg80211_regdomain; +#else + cfg80211_regdomain = + (struct ieee80211_regdomain *) cfg80211_world_regdom; +#endif + + err = wiphy_sysfs_init(); if (err) goto out_fail_sysfs; @@ -425,8 +556,33 @@ static int cfg80211_init(void) ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); + err = regulatory_init(); + if (err) + goto out_fail_reg; + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); + print_regdomain_info(cfg80211_regdomain); + /* The old code still requests for a new regdomain and if + * you have CRDA you get it updated, otherwise you get + * stuck with the static values. We ignore "EU" code as + * that is not a valid ISO / IEC 3166 alpha2 */ + if (ieee80211_regdom[0] != 'E' && + ieee80211_regdom[1] != 'U') + err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, + ieee80211_regdom, NULL); +#else + err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); + if (err) + printk(KERN_ERR "cfg80211: calling CRDA failed - " + "unable to update world regulatory domain, " + "using static definition\n"); +#endif + return 0; +out_fail_reg: + debugfs_remove(ieee80211_debugfs_dir); out_fail_nl80211: unregister_netdevice_notifier(&cfg80211_netdev_notifier); out_fail_notifier: @@ -434,6 +590,7 @@ out_fail_notifier: out_fail_sysfs: return err; } + subsys_initcall(cfg80211_init); static void cfg80211_exit(void) @@ -442,5 +599,6 @@ static void cfg80211_exit(void) nl80211_exit(); unregister_netdevice_notifier(&cfg80211_netdev_notifier); wiphy_sysfs_exit(); + regulatory_exit(); } module_exit(cfg80211_exit); diff --git a/net/wireless/core.h b/net/wireless/core.h index 7a02c356d63d..771cc5cc7658 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -79,6 +79,6 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, char *newname); void ieee80211_set_bitrate_flags(struct wiphy *wiphy); -void wiphy_update_regulatory(struct wiphy *wiphy); +void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); #endif /* __NET_WIRELESS_CORE_H */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 77880ba8b619..1221d726ed50 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -18,6 +18,7 @@ #include #include "core.h" #include "nl80211.h" +#include "reg.h" /* the netlink family */ static struct genl_family nl80211_fam = { @@ -88,6 +89,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { .len = IEEE80211_MAX_MESH_ID_LEN }, [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 }, + [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 }, + [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED }, + [NL80211_ATTR_BSS_CTS_PROT] = { .type = NLA_U8 }, [NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 }, [NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 }, @@ -1599,6 +1603,141 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) return err; } +static const struct nla_policy + reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { + [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, + [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, + [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, + [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, + [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, + [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, +}; + +static int parse_reg_rule(struct nlattr *tb[], + struct ieee80211_reg_rule *reg_rule) +{ + struct ieee80211_freq_range *freq_range = ®_rule->freq_range; + struct ieee80211_power_rule *power_rule = ®_rule->power_rule; + + if (!tb[NL80211_ATTR_REG_RULE_FLAGS]) + return -EINVAL; + if (!tb[NL80211_ATTR_FREQ_RANGE_START]) + return -EINVAL; + if (!tb[NL80211_ATTR_FREQ_RANGE_END]) + return -EINVAL; + if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) + return -EINVAL; + if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) + return -EINVAL; + + reg_rule->flags = nla_get_u32(tb[NL80211_ATTR_REG_RULE_FLAGS]); + + freq_range->start_freq_khz = + nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]); + freq_range->end_freq_khz = + nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]); + freq_range->max_bandwidth_khz = + nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]); + + power_rule->max_eirp = + nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]); + + if (tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]) + power_rule->max_antenna_gain = + nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); + + return 0; +} + +static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) +{ + int r; + char *data = NULL; + + if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) + return -EINVAL; + + data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + /* We ignore world regdom requests with the old regdom setup */ + if (is_world_regdom(data)) + return -EINVAL; +#endif + mutex_lock(&cfg80211_drv_mutex); + r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, NULL); + mutex_unlock(&cfg80211_drv_mutex); + return r; +} + +static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; + struct nlattr *nl_reg_rule; + char *alpha2 = NULL; + int rem_reg_rules = 0, r = 0; + u32 num_rules = 0, rule_idx = 0, size_of_regd; + struct ieee80211_regdomain *rd = NULL; + + if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) + return -EINVAL; + + if (!info->attrs[NL80211_ATTR_REG_RULES]) + return -EINVAL; + + alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); + + nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], + rem_reg_rules) { + num_rules++; + if (num_rules > NL80211_MAX_SUPP_REG_RULES) + goto bad_reg; + } + + if (!reg_is_valid_request(alpha2)) + return -EINVAL; + + size_of_regd = sizeof(struct ieee80211_regdomain) + + (num_rules * sizeof(struct ieee80211_reg_rule)); + + rd = kzalloc(size_of_regd, GFP_KERNEL); + if (!rd) + return -ENOMEM; + + rd->n_reg_rules = num_rules; + rd->alpha2[0] = alpha2[0]; + rd->alpha2[1] = alpha2[1]; + + nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], + rem_reg_rules) { + nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, + nla_data(nl_reg_rule), nla_len(nl_reg_rule), + reg_rule_policy); + r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); + if (r) + goto bad_reg; + + rule_idx++; + + if (rule_idx > NL80211_MAX_SUPP_REG_RULES) + goto bad_reg; + } + + BUG_ON(rule_idx != num_rules); + + mutex_lock(&cfg80211_drv_mutex); + r = set_regdom(rd); + mutex_unlock(&cfg80211_drv_mutex); + if (r) + goto bad_reg; + + return r; + +bad_reg: + kfree(rd); + return -EINVAL; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -1736,6 +1875,18 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_SET_REG, + .doit = nl80211_set_reg, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_REQ_SET_REG, + .doit = nl80211_req_set_reg, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; /* multicast groups */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 855bff4b3250..592b2e391d42 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2,179 +2,758 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright 2007 Johannes Berg + * Copyright 2008 Luis R. Rodriguez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -/* - * This regulatory domain control implementation is highly incomplete, it - * only exists for the purpose of not regressing mac80211. - * - * For now, drivers can restrict the set of allowed channels by either - * not registering those channels or setting the IEEE80211_CHAN_DISABLED - * flag; that flag will only be *set* by this code, never *cleared. +/** + * DOC: Wireless regulatory infrastructure * * The usual implementation is for a driver to read a device EEPROM to * determine which regulatory domain it should be operating under, then * looking up the allowable channels in a driver-local table and finally * registering those channels in the wiphy structure. * - * Alternatively, drivers that trust the regulatory domain control here - * will register a complete set of capabilities and the control code - * will restrict the set by setting the IEEE80211_CHAN_* flags. + * Another set of compliance enforcement is for drivers to use their + * own compliance limits which can be stored on the EEPROM. The host + * driver or firmware may ensure these are used. + * + * In addition to all this we provide an extra layer of regulatory + * conformance. For drivers which do not have any regulatory + * information CRDA provides the complete regulatory solution. + * For others it provides a community effort on further restrictions + * to enhance compliance. + * + * Note: When number of rules --> infinity we will not be able to + * index on alpha2 any more, instead we'll probably have to + * rely on some SHA1 checksum of the regdomain for example. + * */ #include +#include +#include +#include +#include #include +#include #include "core.h" +#include "reg.h" -static char *ieee80211_regdom = "US"; -module_param(ieee80211_regdom, charp, 0444); -MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); +/* To trigger userspace events */ +static struct platform_device *reg_pdev; -struct ieee80211_channel_range { - short start_freq; - short end_freq; - int max_power; - int max_antenna_gain; - u32 flags; +/* Keep the ordering from large to small */ +static u32 supported_bandwidths[] = { + MHZ_TO_KHZ(40), + MHZ_TO_KHZ(20), }; -struct ieee80211_regdomain { - const char *code; - const struct ieee80211_channel_range *ranges; - int n_ranges; -}; +bool is_world_regdom(char *alpha2) +{ + if (!alpha2) + return false; + if (alpha2[0] == '0' && alpha2[1] == '0') + return true; + return false; +} -#define RANGE_PWR(_start, _end, _pwr, _ag, _flags) \ - { _start, _end, _pwr, _ag, _flags } +static bool is_alpha2_set(char *alpha2) +{ + if (!alpha2) + return false; + if (alpha2[0] != 0 && alpha2[1] != 0) + return true; + return false; +} +static bool is_alpha_upper(char letter) +{ + /* ASCII A - Z */ + if (letter >= 65 && letter <= 90) + return true; + return false; +} -/* - * Ideally, in the future, these definitions will be loaded from a - * userspace table via some daemon. - */ -static const struct ieee80211_channel_range ieee80211_US_channels[] = { - /* IEEE 802.11b/g, channels 1..11 */ - RANGE_PWR(2412, 2462, 27, 6, 0), - /* IEEE 802.11a, channel 36*/ - RANGE_PWR(5180, 5180, 23, 6, 0), - /* IEEE 802.11a, channel 40*/ - RANGE_PWR(5200, 5200, 23, 6, 0), - /* IEEE 802.11a, channel 44*/ - RANGE_PWR(5220, 5220, 23, 6, 0), - /* IEEE 802.11a, channels 48..64 */ - RANGE_PWR(5240, 5320, 23, 6, 0), - /* IEEE 802.11a, channels 149..165, outdoor */ - RANGE_PWR(5745, 5825, 30, 6, 0), -}; +static bool is_unknown_alpha2(char *alpha2) +{ + if (!alpha2) + return false; + /* Special case where regulatory domain was built by driver + * but a specific alpha2 cannot be determined */ + if (alpha2[0] == '9' && alpha2[1] == '9') + return true; + return false; +} -static const struct ieee80211_channel_range ieee80211_JP_channels[] = { - /* IEEE 802.11b/g, channels 1..14 */ - RANGE_PWR(2412, 2484, 20, 6, 0), - /* IEEE 802.11a, channels 34..48 */ - RANGE_PWR(5170, 5240, 20, 6, IEEE80211_CHAN_PASSIVE_SCAN), - /* IEEE 802.11a, channels 52..64 */ - RANGE_PWR(5260, 5320, 20, 6, IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_RADAR), -}; +static bool is_an_alpha2(char *alpha2) +{ + if (!alpha2) + return false; + if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1])) + return true; + return false; +} -static const struct ieee80211_channel_range ieee80211_EU_channels[] = { - /* IEEE 802.11b/g, channels 1..13 */ - RANGE_PWR(2412, 2472, 20, 6, 0), - /* IEEE 802.11a, channel 36*/ - RANGE_PWR(5180, 5180, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN), - /* IEEE 802.11a, channel 40*/ - RANGE_PWR(5200, 5200, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN), - /* IEEE 802.11a, channel 44*/ - RANGE_PWR(5220, 5220, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN), - /* IEEE 802.11a, channels 48..64 */ - RANGE_PWR(5240, 5320, 23, 6, IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_RADAR), - /* IEEE 802.11a, channels 100..140 */ - RANGE_PWR(5500, 5700, 30, 6, IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_RADAR), -}; +static bool alpha2_equal(char *alpha2_x, char *alpha2_y) +{ + if (!alpha2_x || !alpha2_y) + return false; + if (alpha2_x[0] == alpha2_y[0] && + alpha2_x[1] == alpha2_y[1]) + return true; + return false; +} + +static bool regdom_changed(char *alpha2) +{ + if (!cfg80211_regdomain) + return true; + if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) + return false; + return true; +} + +/* This lets us keep regulatory code which is updated on a regulatory + * basis in userspace. */ +static int call_crda(const char *alpha2) +{ + char country_env[9 + 2] = "COUNTRY="; + char *envp[] = { + country_env, + NULL + }; + + if (!is_world_regdom((char *) alpha2)) + printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", + alpha2[0], alpha2[1]); + else +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + return -EINVAL; +#else + printk(KERN_INFO "cfg80211: Calling CRDA to update world " + "regulatory domain\n"); +#endif + + country_env[8] = alpha2[0]; + country_env[9] = alpha2[1]; + + return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, envp); +} + +/* This has the logic which determines when a new request + * should be ignored. */ +static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, + char *alpha2, struct ieee80211_regdomain *rd) +{ + struct regulatory_request *last_request = NULL; -#define REGDOM(_code) \ - { \ - .code = __stringify(_code), \ - .ranges = ieee80211_ ##_code## _channels, \ - .n_ranges = ARRAY_SIZE(ieee80211_ ##_code## _channels), \ + /* All initial requests are respected */ + if (list_empty(®ulatory_requests)) + return 0; + + last_request = list_first_entry(®ulatory_requests, + struct regulatory_request, list); + + switch (set_by) { + case REGDOM_SET_BY_INIT: + return -EINVAL; + case REGDOM_SET_BY_CORE: + /* Always respect new wireless core hints, should only + * come in for updating the world regulatory domain at init + * anyway */ + return 0; + case REGDOM_SET_BY_COUNTRY_IE: + if (last_request->initiator == set_by) { + if (last_request->wiphy != wiphy) { + /* Two cards with two APs claiming different + * different Country IE alpha2s! + * You're special!! */ + if (!alpha2_equal(last_request->alpha2, + cfg80211_regdomain->alpha2)) { + /* XXX: Deal with conflict, consider + * building a new one out of the + * intersection */ + WARN_ON(1); + return -EOPNOTSUPP; + } + return -EALREADY; + } + /* Two consecutive Country IE hints on the same wiphy */ + if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) + return 0; + return -EALREADY; + } + if (WARN_ON(!is_alpha2_set(alpha2) || !is_an_alpha2(alpha2)), + "Invalid Country IE regulatory hint passed " + "to the wireless core\n") + return -EINVAL; + /* We ignore Country IE hints for now, as we haven't yet + * added the dot11MultiDomainCapabilityEnabled flag + * for wiphys */ + return 1; + case REGDOM_SET_BY_DRIVER: + BUG_ON(!wiphy); + if (last_request->initiator == set_by) { + /* Two separate drivers hinting different things, + * this is possible if you have two devices present + * on a system with different EEPROM regulatory + * readings. XXX: Do intersection, we support only + * the first regulatory hint for now */ + if (last_request->wiphy != wiphy) + return -EALREADY; + if (rd) + return -EALREADY; + /* Driver should not be trying to hint different + * regulatory domains! */ + BUG_ON(!alpha2_equal(alpha2, + cfg80211_regdomain->alpha2)); + return -EALREADY; + } + if (last_request->initiator == REGDOM_SET_BY_CORE) + return 0; + /* XXX: Handle intersection, and add the + * dot11MultiDomainCapabilityEnabled flag to wiphy. For now + * we assume the driver has this set to false, following the + * 802.11d dot11MultiDomainCapabilityEnabled documentation */ + if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) + return 0; + return 0; + case REGDOM_SET_BY_USER: + if (last_request->initiator == set_by || + last_request->initiator == REGDOM_SET_BY_CORE) + return 0; + /* Drivers can use their wiphy's reg_notifier() + * to override any information */ + if (last_request->initiator == REGDOM_SET_BY_DRIVER) + return 0; + /* XXX: Handle intersection */ + if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) + return -EOPNOTSUPP; + return 0; + default: + return -EINVAL; } +} -static const struct ieee80211_regdomain ieee80211_regdoms[] = { - REGDOM(US), - REGDOM(JP), - REGDOM(EU), -}; +static bool __reg_is_valid_request(char *alpha2, + struct regulatory_request **request) +{ + struct regulatory_request *req; + if (list_empty(®ulatory_requests)) + return false; + list_for_each_entry(req, ®ulatory_requests, list) { + if (alpha2_equal(req->alpha2, alpha2)) { + *request = req; + return true; + } + } + return false; +} +/* Used by nl80211 before kmalloc'ing our regulatory domain */ +bool reg_is_valid_request(char *alpha2) +{ + struct regulatory_request *request = NULL; + return __reg_is_valid_request(alpha2, &request); +} -static const struct ieee80211_regdomain *get_regdom(void) +/* Sanity check on a regulatory rule */ +static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) { - static const struct ieee80211_channel_range - ieee80211_world_channels[] = { - /* IEEE 802.11b/g, channels 1..11 */ - RANGE_PWR(2412, 2462, 27, 6, 0), - }; - static const struct ieee80211_regdomain regdom_world = REGDOM(world); - int i; + struct ieee80211_freq_range *freq_range = &rule->freq_range; + u32 freq_diff; + + if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) + return false; + + if (freq_range->start_freq_khz > freq_range->end_freq_khz) + return false; + + freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; + + if (freq_range->max_bandwidth_khz > freq_diff) + return false; + + return true; +} + +static bool is_valid_rd(struct ieee80211_regdomain *rd) +{ + struct ieee80211_reg_rule *reg_rule = NULL; + unsigned int i; - for (i = 0; i < ARRAY_SIZE(ieee80211_regdoms); i++) - if (strcmp(ieee80211_regdom, ieee80211_regdoms[i].code) == 0) - return &ieee80211_regdoms[i]; + if (!rd->n_reg_rules) + return false; - return ®dom_world; + for (i = 0; i < rd->n_reg_rules; i++) { + reg_rule = &rd->reg_rules[i]; + if (!is_valid_reg_rule(reg_rule)) + return false; + } + + return true; } +/* Returns value in KHz */ +static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, + u32 freq) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { + u32 start_freq_khz = freq - supported_bandwidths[i]/2; + u32 end_freq_khz = freq + supported_bandwidths[i]/2; + if (start_freq_khz >= freq_range->start_freq_khz && + end_freq_khz <= freq_range->end_freq_khz) + return supported_bandwidths[i]; + } + return 0; +} -static void handle_channel(struct ieee80211_channel *chan, - const struct ieee80211_regdomain *rd) +/* XXX: add support for the rest of enum nl80211_reg_rule_flags, we may + * want to just have the channel structure use these */ +static u32 map_regdom_flags(u32 rd_flags) +{ + u32 channel_flags = 0; + if (rd_flags & NL80211_RRF_PASSIVE_SCAN) + channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN; + if (rd_flags & NL80211_RRF_NO_IBSS) + channel_flags |= IEEE80211_CHAN_NO_IBSS; + if (rd_flags & NL80211_RRF_DFS) + channel_flags |= IEEE80211_CHAN_RADAR; + return channel_flags; +} + +/** + * freq_reg_info - get regulatory information for the given frequency + * @center_freq: Frequency in KHz for which we want regulatory information for + * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one + * you can set this to 0. If this frequency is allowed we then set + * this value to the maximum allowed bandwidth. + * @reg_rule: the regulatory rule which we have for this frequency + * + * Use this function to get the regulatory rule for a specific frequency. + */ +static int freq_reg_info(u32 center_freq, u32 *bandwidth, + const struct ieee80211_reg_rule **reg_rule) { int i; - u32 flags = chan->orig_flags; - const struct ieee80211_channel_range *rg = NULL; + u32 max_bandwidth = 0; - for (i = 0; i < rd->n_ranges; i++) { - if (rd->ranges[i].start_freq <= chan->center_freq && - chan->center_freq <= rd->ranges[i].end_freq) { - rg = &rd->ranges[i]; + if (!cfg80211_regdomain) + return -EINVAL; + + for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) { + const struct ieee80211_reg_rule *rr; + const struct ieee80211_freq_range *fr = NULL; + const struct ieee80211_power_rule *pr = NULL; + + rr = &cfg80211_regdomain->reg_rules[i]; + fr = &rr->freq_range; + pr = &rr->power_rule; + max_bandwidth = freq_max_bandwidth(fr, center_freq); + if (max_bandwidth && *bandwidth <= max_bandwidth) { + *reg_rule = rr; + *bandwidth = max_bandwidth; break; } } - if (!rg) { - /* not found */ + return !max_bandwidth; +} + +static void handle_channel(struct ieee80211_channel *chan) +{ + int r; + u32 flags = chan->orig_flags; + u32 max_bandwidth = 0; + const struct ieee80211_reg_rule *reg_rule = NULL; + const struct ieee80211_power_rule *power_rule = NULL; + + r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq), + &max_bandwidth, ®_rule); + + if (r) { flags |= IEEE80211_CHAN_DISABLED; chan->flags = flags; return; } - chan->flags = flags; + power_rule = ®_rule->power_rule; + + chan->flags = flags | map_regdom_flags(reg_rule->flags); chan->max_antenna_gain = min(chan->orig_mag, - rg->max_antenna_gain); + (int) MBI_TO_DBI(power_rule->max_antenna_gain)); + chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); if (chan->orig_mpwr) - chan->max_power = min(chan->orig_mpwr, rg->max_power); + chan->max_power = min(chan->orig_mpwr, + (int) MBM_TO_DBM(power_rule->max_eirp)); else - chan->max_power = rg->max_power; + chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); } -static void handle_band(struct ieee80211_supported_band *sband, - const struct ieee80211_regdomain *rd) +static void handle_band(struct ieee80211_supported_band *sband) { int i; for (i = 0; i < sband->n_channels; i++) - handle_channel(&sband->channels[i], rd); + handle_channel(&sband->channels[i]); } -void wiphy_update_regulatory(struct wiphy *wiphy) +static void update_all_wiphy_regulatory(enum reg_set_by setby) { - enum ieee80211_band band; - const struct ieee80211_regdomain *rd = get_regdom(); + struct cfg80211_registered_device *drv; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) + list_for_each_entry(drv, &cfg80211_drv_list, list) + wiphy_update_regulatory(&drv->wiphy, setby); +} + +void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) +{ + enum ieee80211_band band; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) - handle_band(wiphy->bands[band], rd); + handle_band(wiphy->bands[band]); + if (wiphy->reg_notifier) + wiphy->reg_notifier(wiphy, setby); + } +} + +/* Caller must hold &cfg80211_drv_mutex */ +int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, + const char *alpha2, struct ieee80211_regdomain *rd) +{ + struct regulatory_request *request; + char *rd_alpha2; + int r = 0; + + r = ignore_request(wiphy, set_by, (char *) alpha2, rd); + if (r) + return r; + + if (rd) + rd_alpha2 = rd->alpha2; + else + rd_alpha2 = (char *) alpha2; + + switch (set_by) { + case REGDOM_SET_BY_CORE: + case REGDOM_SET_BY_COUNTRY_IE: + case REGDOM_SET_BY_DRIVER: + case REGDOM_SET_BY_USER: + request = kzalloc(sizeof(struct regulatory_request), + GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->alpha2[0] = rd_alpha2[0]; + request->alpha2[1] = rd_alpha2[1]; + request->initiator = set_by; + request->wiphy = wiphy; + + list_add_tail(&request->list, ®ulatory_requests); + if (rd) + break; + r = call_crda(alpha2); +#ifndef CONFIG_WIRELESS_OLD_REGULATORY + if (r) + printk(KERN_ERR "cfg80211: Failed calling CRDA\n"); +#endif + break; + default: + r = -ENOTSUPP; + break; + } + + return r; +} + +/* If rd is not NULL and if this call fails the caller must free it */ +int regulatory_hint(struct wiphy *wiphy, const char *alpha2, + struct ieee80211_regdomain *rd) +{ + int r; + BUG_ON(!rd && !alpha2); + + mutex_lock(&cfg80211_drv_mutex); + + r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, rd); + if (r || !rd) + goto unlock_and_exit; + + /* If the driver passed a regulatory domain we skipped asking + * userspace for one so we can now go ahead and set it */ + r = set_regdom(rd); + +unlock_and_exit: + mutex_unlock(&cfg80211_drv_mutex); + return r; +} +EXPORT_SYMBOL(regulatory_hint); + + +static void print_rd_rules(struct ieee80211_regdomain *rd) +{ + unsigned int i; + struct ieee80211_reg_rule *reg_rule = NULL; + struct ieee80211_freq_range *freq_range = NULL; + struct ieee80211_power_rule *power_rule = NULL; + + printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " + "(max_antenna_gain, max_eirp)\n"); + + for (i = 0; i < rd->n_reg_rules; i++) { + reg_rule = &rd->reg_rules[i]; + freq_range = ®_rule->freq_range; + power_rule = ®_rule->power_rule; + + /* There may not be documentation for max antenna gain + * in certain regions */ + if (power_rule->max_antenna_gain) + printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " + "(%d mBi, %d mBm)\n", + freq_range->start_freq_khz, + freq_range->end_freq_khz, + freq_range->max_bandwidth_khz, + power_rule->max_antenna_gain, + power_rule->max_eirp); + else + printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " + "(N/A, %d mBm)\n", + freq_range->start_freq_khz, + freq_range->end_freq_khz, + freq_range->max_bandwidth_khz, + power_rule->max_eirp); + } +} + +static void print_regdomain(struct ieee80211_regdomain *rd) +{ + + if (is_world_regdom(rd->alpha2)) + printk(KERN_INFO "cfg80211: World regulatory " + "domain updated:\n"); + else { + if (is_unknown_alpha2(rd->alpha2)) + printk(KERN_INFO "cfg80211: Regulatory domain " + "changed to driver built-in settings " + "(unknown country)\n"); + else + printk(KERN_INFO "cfg80211: Regulatory domain " + "changed to country: %c%c\n", + rd->alpha2[0], rd->alpha2[1]); + } + print_rd_rules(rd); +} + +void print_regdomain_info(struct ieee80211_regdomain *rd) +{ + printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", + rd->alpha2[0], rd->alpha2[1]); + print_rd_rules(rd); +} + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + +static bool is_old_static_regdom(struct ieee80211_regdomain *rd) +{ + if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) + return true; + return false; +} + +/* The old crap never deals with a world regulatory domain, it only + * deals with the static regulatory domain passed and if possible + * an updated "US" or "JP" regulatory domain. We do however store the + * old static regulatory domain in cfg80211_world_regdom for convenience + * of use here */ +static void reset_regdomains_static(void) +{ + if (!is_old_static_regdom(cfg80211_regdomain)) + kfree(cfg80211_regdomain); + /* This is setting the regdom to the old static regdom */ + cfg80211_regdomain = + (struct ieee80211_regdomain *) cfg80211_world_regdom; +} +#else +static void reset_regdomains(void) +{ + if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { + if (cfg80211_world_regdom == cfg80211_regdomain) { + kfree(cfg80211_regdomain); + } else { + kfree(cfg80211_world_regdom); + kfree(cfg80211_regdomain); + } + } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) + kfree(cfg80211_regdomain); + + cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; + cfg80211_regdomain = NULL; +} + +/* Dynamic world regulatory domain requested by the wireless + * core upon initialization */ +static void update_world_regdomain(struct ieee80211_regdomain *rd) +{ + BUG_ON(list_empty(®ulatory_requests)); + + reset_regdomains(); + + cfg80211_world_regdom = rd; + cfg80211_regdomain = rd; +} +#endif + +static int __set_regdom(struct ieee80211_regdomain *rd) +{ + struct regulatory_request *request = NULL; + + /* Some basic sanity checks first */ + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + /* We ignore the world regdom with the old static regdomains setup + * as there is no point to it with satic regulatory definitions :( + * Don't worry this shit will be removed soon... */ + if (is_world_regdom(rd->alpha2)) + return -EINVAL; +#else + if (is_world_regdom(rd->alpha2)) { + if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) + return -EINVAL; + update_world_regdomain(rd); + return 0; + } +#endif + + if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && + !is_unknown_alpha2(rd->alpha2)) + return -EINVAL; + + if (list_empty(®ulatory_requests)) + return -EINVAL; + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + /* Static "US" and "JP" will be overridden, but just once */ + if (!is_old_static_regdom(cfg80211_regdomain) && + !regdom_changed(rd->alpha2)) + return -EINVAL; +#else + if (!regdom_changed(rd->alpha2)) + return -EINVAL; +#endif + + /* Now lets set the regulatory domain, update all driver channels + * and finally inform them of what we have done, in case they want + * to review or adjust their own settings based on their own + * internal EEPROM data */ + + if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) + return -EINVAL; + +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + reset_regdomains_static(); +#else + reset_regdomains(); +#endif + + /* Country IE parsing coming soon */ + switch (request->initiator) { + case REGDOM_SET_BY_CORE: + case REGDOM_SET_BY_DRIVER: + case REGDOM_SET_BY_USER: + if (!is_valid_rd(rd)) { + printk(KERN_ERR "cfg80211: Invalid " + "regulatory domain detected:\n"); + print_regdomain_info(rd); + return -EINVAL; + } + break; + case REGDOM_SET_BY_COUNTRY_IE: /* Not yet */ + WARN_ON(1); + default: + return -EOPNOTSUPP; + } + + /* Tada! */ + cfg80211_regdomain = rd; + request->granted = 1; + + return 0; +} + + +/* Use this call to set the current regulatory domain. Conflicts with + * multiple drivers can be ironed out later. Caller must've already + * kmalloc'd the rd structure. If this calls fails you should kfree() + * the passed rd. Caller must hold cfg80211_drv_mutex */ +int set_regdom(struct ieee80211_regdomain *rd) +{ + struct regulatory_request *this_request = NULL, *prev_request = NULL; + int r; + + if (!list_empty(®ulatory_requests)) + prev_request = list_first_entry(®ulatory_requests, + struct regulatory_request, list); + + /* Note that this doesn't update the wiphys, this is done below */ + r = __set_regdom(rd); + if (r) + return r; + + BUG_ON((!__reg_is_valid_request(rd->alpha2, &this_request))); + + /* The initial standard core update of the world regulatory domain, no + * need to keep that request info around if it didn't fail. */ + if (is_world_regdom(rd->alpha2) && + this_request->initiator == REGDOM_SET_BY_CORE && + this_request->granted) { + list_del(&this_request->list); + kfree(this_request); + this_request = NULL; + } + + /* Remove old requests, we only leave behind the last one */ + if (prev_request) { + list_del(&prev_request->list); + kfree(prev_request); + prev_request = NULL; + } + + /* This would make this whole thing pointless */ + BUG_ON(rd != cfg80211_regdomain); + + /* update all wiphys now with the new established regulatory domain */ + update_all_wiphy_regulatory(this_request->initiator); + + print_regdomain(rd); + + return r; +} + +int regulatory_init(void) +{ + reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); + if (IS_ERR(reg_pdev)) + return PTR_ERR(reg_pdev); + return 0; +} + +void regulatory_exit(void) +{ + struct regulatory_request *req, *req_tmp; + mutex_lock(&cfg80211_drv_mutex); +#ifdef CONFIG_WIRELESS_OLD_REGULATORY + reset_regdomains_static(); +#else + reset_regdomains(); +#endif + list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { + list_del(&req->list); + kfree(req); + } + platform_device_unregister(reg_pdev); + mutex_unlock(&cfg80211_drv_mutex); } diff --git a/net/wireless/reg.h b/net/wireless/reg.h new file mode 100644 index 000000000000..d75fd0232972 --- /dev/null +++ b/net/wireless/reg.h @@ -0,0 +1,44 @@ +#ifndef __NET_WIRELESS_REG_H +#define __NET_WIRELESS_REG_H + +extern const struct ieee80211_regdomain world_regdom; +#ifdef CONFIG_WIRELESS_OLD_REGULATORY +extern const struct ieee80211_regdomain us_regdom; +extern const struct ieee80211_regdomain jp_regdom; +extern const struct ieee80211_regdomain eu_regdom; +#endif + +extern struct ieee80211_regdomain *cfg80211_regdomain; +extern struct ieee80211_regdomain *cfg80211_world_regdom; +extern struct list_head regulatory_requests; + +struct regdom_last_setby { + struct wiphy *wiphy; + u8 initiator; +}; + +/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ +struct regulatory_request { + struct list_head list; + struct wiphy *wiphy; + int granted; + enum reg_set_by initiator; + char alpha2[2]; +}; + +bool is_world_regdom(char *alpha2); +bool reg_is_valid_request(char *alpha2); + +int set_regdom(struct ieee80211_regdomain *rd); +int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by, + const char *alpha2); + +int regulatory_init(void); +void regulatory_exit(void); + +void print_regdomain_info(struct ieee80211_regdomain *); + +/* If a char is A-Z */ +#define IS_ALPHA(letter) (letter >= 65 && letter <= 90) + +#endif /* __NET_WIRELESS_REG_H */ -- cgit v1.2.3 From 24723d1bc9da79a53d0495b9cf9ee18747121b03 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:46 +0200 Subject: mac80211: move ieee80211_sta_expire ieee80211_sta_expire uses the internal __sta_info_unlink function which can become static if this function is moved to sta_info.c. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 26 -------------------------- net/mac80211/sta_info.c | 28 +++++++++++++++++++++++++++- net/mac80211/sta_info.h | 3 ++- 3 files changed, 29 insertions(+), 28 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2c06f6965b7d..ffc47c81a161 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1913,32 +1913,6 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) } -static void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta, *tmp; - LIST_HEAD(tmp_list); - DECLARE_MAC_BUF(mac); - unsigned long flags; - - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry_safe(sta, tmp, &local->sta_list, list) - if (time_after(jiffies, sta->last_rx + exp_time)) { -#ifdef CONFIG_MAC80211_IBSS_DEBUG - printk(KERN_DEBUG "%s: expiring inactive STA %s\n", - sdata->dev->name, print_mac(mac, sta->addr)); -#endif - __sta_info_unlink(&sta); - if (sta) - list_add(&sta->list, &tmp_list); - } - spin_unlock_irqrestore(&local->sta_lock, flags); - - list_for_each_entry_safe(sta, tmp, &tmp_list, list) - sta_info_destroy(sta); -} - - static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2ba653b9d69..3370b2625633 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -424,7 +424,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta) spin_unlock_irqrestore(&sta->local->sta_lock, flags); } -void __sta_info_unlink(struct sta_info **sta) +static void __sta_info_unlink(struct sta_info **sta) { struct ieee80211_local *local = (*sta)->local; struct ieee80211_sub_if_data *sdata = (*sta)->sdata; @@ -802,3 +802,29 @@ void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) schedule_work(&local->sta_flush_work); spin_unlock_irqrestore(&local->sta_lock, flags); } + +void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, + unsigned long exp_time) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta, *tmp; + LIST_HEAD(tmp_list); + DECLARE_MAC_BUF(mac); + unsigned long flags; + + spin_lock_irqsave(&local->sta_lock, flags); + list_for_each_entry_safe(sta, tmp, &local->sta_list, list) + if (time_after(jiffies, sta->last_rx + exp_time)) { +#ifdef CONFIG_MAC80211_IBSS_DEBUG + printk(KERN_DEBUG "%s: expiring inactive STA %s\n", + sdata->dev->name, print_mac(mac, sta->addr)); +#endif + __sta_info_unlink(&sta); + if (sta) + list_add(&sta->list, &tmp_list); + } + spin_unlock_irqrestore(&local->sta_lock, flags); + + list_for_each_entry_safe(sta, tmp, &tmp_list, list) + sta_info_destroy(sta); +} diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4a581a5b5766..220079900991 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -452,7 +452,6 @@ int sta_info_insert(struct sta_info *sta); * has already unlinked it. */ void sta_info_unlink(struct sta_info **sta); -void __sta_info_unlink(struct sta_info **sta); void sta_info_destroy(struct sta_info *sta); void sta_info_set_tim_bit(struct sta_info *sta); @@ -464,5 +463,7 @@ void sta_info_stop(struct ieee80211_local *local); int sta_info_flush(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); +void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, + unsigned long exp_time); #endif /* STA_INFO_H */ -- cgit v1.2.3 From a1678f84bff9b20807f7f6a45ebfb56a0c02b353 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:47 +0200 Subject: mac80211: move STA timer restart This I shouldn't have moved to the scan implementation, move it back to the MLME where it belongs, to the notification. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 13 +++++++++++++ net/mac80211/scan.c | 14 -------------- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ffc47c81a161..809fb9160899 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2594,6 +2594,13 @@ void ieee80211_sta_work(struct work_struct *work) } } +static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) +{ + if (sdata->vif.type == IEEE80211_IF_TYPE_STA || + ieee80211_vif_is_mesh(&sdata->vif)) + ieee80211_sta_timer((unsigned long)sdata); +} + void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata = local->scan_sdata; @@ -2606,4 +2613,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) !ieee80211_sta_active_ibss(sdata))) ieee80211_sta_find_ibss(sdata, ifsta); } + + /* Restart STA timers */ + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + ieee80211_restart_sta_timer(sdata); + rcu_read_unlock(); } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 010781b806f3..f8b296bed0b9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -424,13 +424,6 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, ieee80211_tx_skb(sdata, skb, 0); } -static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) -{ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_sta_timer((unsigned long)sdata); -} - void ieee80211_scan_completed(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); @@ -446,11 +439,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " "channel after scan\n", wiphy_name(local->hw.wiphy)); - /* Restart STA timer for HW scan case */ - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) - ieee80211_restart_sta_timer(sdata); - rcu_read_unlock(); goto done; } @@ -483,8 +471,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) } } else netif_tx_wake_all_queues(sdata->dev); - - ieee80211_restart_sta_timer(sdata); } rcu_read_unlock(); -- cgit v1.2.3 From 7c95069522d02ff144cd421be6618dce619caf7e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:48 +0200 Subject: mac80211: dont set REQ_RUN when scan finishes The timer restart is done wrongly, we shouldn't set the REQ_RUN bit when the scan has finished if it hadn't been set before the scan started. If the timer fires during the scan, it will set REQ_RUN and then we can run the work for it, if it didn't fire then we shouldn't run its work either. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 809fb9160899..ef73f8953724 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2598,7 +2598,8 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) { if (sdata->vif.type == IEEE80211_IF_TYPE_STA || ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_sta_timer((unsigned long)sdata); + queue_work(sdata->local->hw.workqueue, + &sdata->u.sta.work); } void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) -- cgit v1.2.3 From 472dbc45dc1966284de72d7de15690c17ed2cf33 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:49 +0200 Subject: mac80211: split off mesh handling entirely This patch splits off mesh handling from the STA/IBSS. Unfortunately it increases mesh code size a bit, but I think it makes things clearer. The patch also reduces per-interface run-time memory usage. Also clean up a few places where ifdef is not required. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 6 +- net/mac80211/debugfs_netdev.c | 38 ++--- net/mac80211/ieee80211_i.h | 101 +++++++------ net/mac80211/iface.c | 13 +- net/mac80211/main.c | 13 +- net/mac80211/mesh.c | 328 +++++++++++++++++++++++++++++++++------- net/mac80211/mesh.h | 15 +- net/mac80211/mesh_hwmp.c | 98 ++++++------ net/mac80211/mesh_pathtbl.c | 8 +- net/mac80211/mesh_plink.c | 18 +-- net/mac80211/mlme.c | 83 +--------- net/mac80211/rc80211_pid_algo.c | 7 +- net/mac80211/rx.c | 8 +- net/mac80211/scan.c | 1 + net/mac80211/tx.c | 15 +- 15 files changed, 457 insertions(+), 295 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5a3bdaad6c19..6ec2127f9a60 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -116,9 +116,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, return ret; if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) - ieee80211_if_sta_set_mesh_id(&sdata->u.sta, - params->mesh_id_len, - params->mesh_id); + ieee80211_sdata_set_mesh_id(sdata, + params->mesh_id_len, + params->mesh_id); if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) return 0; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8165df578c92..0fa7681a3d20 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -207,37 +207,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); #ifdef CONFIG_MAC80211_MESH /* Mesh stats attributes */ -IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC); -IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC); +IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); +IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); IEEE80211_IF_FILE(dropped_frames_no_route, - u.sta.mshstats.dropped_frames_no_route, DEC); -IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC); + u.mesh.mshstats.dropped_frames_no_route, DEC); +IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); /* Mesh parameters */ IEEE80211_IF_WFILE(dot11MeshMaxRetries, - u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8); + u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8); IEEE80211_IF_WFILE(dot11MeshRetryTimeout, - u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16); + u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16); IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, - u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16); + u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, - u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16); -IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8); -IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8); + u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16); +IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8); +IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8); IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, - u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); + u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, - u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); + u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, - u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); + u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, - u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); + u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, - u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); + u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); IEEE80211_IF_WFILE(path_refresh_time, - u.sta.mshcfg.path_refresh_time, DEC, u32); + u.mesh.mshcfg.path_refresh_time, DEC, u32); IEEE80211_IF_WFILE(min_discovery_timeout, - u.sta.mshcfg.min_discovery_timeout, DEC, u16); + u.mesh.mshcfg.min_discovery_timeout, DEC, u16); #endif @@ -350,7 +350,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) add_mesh_stats(sdata); add_mesh_config(sdata); #endif - /* fall through */ + break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: add_sta_files(sdata); @@ -487,7 +487,7 @@ static void del_files(struct ieee80211_sub_if_data *sdata) del_mesh_stats(sdata); del_mesh_config(sdata); #endif - /* fall through */ + break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: del_sta_files(sdata); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f334e4c3d66..cac0b1334548 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -308,7 +308,6 @@ enum ieee80211_sta_mlme_state { IEEE80211_STA_MLME_ASSOCIATED, IEEE80211_STA_MLME_IBSS_SEARCH, IEEE80211_STA_MLME_IBSS_JOINED, - IEEE80211_STA_MLME_MESH_UP }; /* bitfield of allowed auth algs */ @@ -325,34 +324,6 @@ struct ieee80211_if_sta { size_t ssid_len; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; -#ifdef CONFIG_MAC80211_MESH - struct timer_list mesh_path_timer; - u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; - size_t mesh_id_len; - /* Active Path Selection Protocol Identifier */ - u8 mesh_pp_id[4]; - /* Active Path Selection Metric Identifier */ - u8 mesh_pm_id[4]; - /* Congestion Control Mode Identifier */ - u8 mesh_cc_id[4]; - /* Local mesh Destination Sequence Number */ - u32 dsn; - /* Last used PREQ ID */ - u32 preq_id; - atomic_t mpaths; - /* Timestamp of last DSN update */ - unsigned long last_dsn_update; - /* Timestamp of last DSN sent */ - unsigned long last_preq; - struct mesh_rmc *rmc; - spinlock_t mesh_preq_queue_lock; - struct mesh_preq_queue preq_queue; - int preq_queue_len; - struct mesh_stats mshstats; - struct mesh_config mshcfg; - u32 mesh_seqnum; - bool accepting_plinks; -#endif u16 aid; u16 ap_capab, capab; u8 *extra_ie; /* to be added to the end of AssocReq */ @@ -387,20 +358,47 @@ struct ieee80211_if_sta { int num_beacons; /* number of TXed beacon frames by this STA */ }; -static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta, - u8 mesh_id_len, u8 *mesh_id) -{ -#ifdef CONFIG_MAC80211_MESH - ifsta->mesh_id_len = mesh_id_len; - memcpy(ifsta->mesh_id, mesh_id, mesh_id_len); -#endif -} +struct ieee80211_if_mesh { + struct work_struct work; + struct timer_list housekeeping_timer; + struct timer_list mesh_path_timer; + struct sk_buff_head skb_queue; + + bool housekeeping; + + u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; + size_t mesh_id_len; + /* Active Path Selection Protocol Identifier */ + u8 mesh_pp_id[4]; + /* Active Path Selection Metric Identifier */ + u8 mesh_pm_id[4]; + /* Congestion Control Mode Identifier */ + u8 mesh_cc_id[4]; + /* Local mesh Destination Sequence Number */ + u32 dsn; + /* Last used PREQ ID */ + u32 preq_id; + atomic_t mpaths; + /* Timestamp of last DSN update */ + unsigned long last_dsn_update; + /* Timestamp of last DSN sent */ + unsigned long last_preq; + struct mesh_rmc *rmc; + spinlock_t mesh_preq_queue_lock; + struct mesh_preq_queue preq_queue; + int preq_queue_len; + struct mesh_stats mshstats; + struct mesh_config mshcfg; + u32 mesh_seqnum; + bool accepting_plinks; + int num_beacons; +}; #ifdef CONFIG_MAC80211_MESH -#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ - do { (sta)->mshstats.name++; } while (0) +#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ + do { (msh)->mshstats.name++; } while (0) #else -#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ +#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ do { } while (0) #endif @@ -455,6 +453,9 @@ struct ieee80211_sub_if_data { struct ieee80211_if_wds wds; struct ieee80211_if_vlan vlan; struct ieee80211_if_sta sta; +#ifdef CONFIG_MAC80211_MESH + struct ieee80211_if_mesh mesh; +#endif u32 mntr_flags; } u; @@ -548,6 +549,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) return container_of(p, struct ieee80211_sub_if_data, vif); } +static inline void +ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, + u8 mesh_id_len, u8 *mesh_id) +{ +#ifdef CONFIG_MAC80211_MESH + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + ifmsh->mesh_id_len = mesh_id_len; + memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); +#else + WARN_ON(1); +#endif +} + enum { IEEE80211_RX_MSG = 1, IEEE80211_TX_STATUS_MSG = 2, @@ -935,13 +949,6 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_sta_bss *bss); -#ifdef CONFIG_MAC80211_MESH -void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); -#else -static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) -{} -#endif - /* interface handling */ void ieee80211_if_setup(struct net_device *dev); int ieee80211_if_add(struct ieee80211_local *local, const char *name, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 672cec60a2fb..ddbaa417e2ec 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -54,10 +54,9 @@ static void ieee80211_teardown_sdata(struct net_device *dev) break; case IEEE80211_IF_TYPE_MESH_POINT: - /* Allow compiler to elide mesh_rmc_free call. */ if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_rmc_free(sdata); - /* fall through */ + break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: kfree(sdata->u.sta.extra_ie); @@ -100,7 +99,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, skb_queue_head_init(&sdata->u.ap.ps_bc_buf); INIT_LIST_HEAD(&sdata->u.ap.vlans); break; - case IEEE80211_IF_TYPE_MESH_POINT: case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: ifsta = &sdata->u.sta; @@ -117,7 +115,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, IEEE80211_STA_AUTO_CHANNEL_SEL; if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) ifsta->flags |= IEEE80211_STA_WMM_ENABLED; - + break; + case IEEE80211_IF_TYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) ieee80211_mesh_init_sdata(sdata); break; @@ -225,9 +224,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, if (ieee80211_vif_is_mesh(&sdata->vif) && params && params->mesh_id_len) - ieee80211_if_sta_set_mesh_id(&sdata->u.sta, - params->mesh_id_len, - params->mesh_id); + ieee80211_sdata_set_mesh_id(sdata, + params->mesh_id_len, + params->mesh_id); list_add_tail_rcu(&sdata->list, &local->interfaces); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6a7f4fae18c2..522fe6176485 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -252,6 +252,8 @@ static int ieee80211_open(struct net_device *dev) sdata->bss = &sdata->u.ap; break; case IEEE80211_IF_TYPE_MESH_POINT: + if (!ieee80211_vif_is_mesh(&sdata->vif)) + break; /* mesh ifaces must set allmulti to forward mcast traffic */ atomic_inc(&local->iff_allmultis); break; @@ -540,10 +542,6 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_configure_filter(local); netif_addr_unlock_bh(local->mdev); break; - case IEEE80211_IF_TYPE_MESH_POINT: - /* allmulti is always set on mesh ifaces */ - atomic_dec(&local->iff_allmultis); - /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; @@ -571,6 +569,13 @@ static int ieee80211_stop(struct net_device *dev) sdata->u.sta.extra_ie = NULL; sdata->u.sta.extra_ie_len = 0; /* fall through */ + case IEEE80211_IF_TYPE_MESH_POINT: + if (ieee80211_vif_is_mesh(&sdata->vif)) { + /* allmulti is always set on mesh ifaces */ + atomic_dec(&local->iff_allmultis); + ieee80211_stop_mesh(sdata); + } + /* fall through */ default: conf.vif = &sdata->vif; conf.type = sdata->vif.type; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 3ccb3599c04f..9e47725cc592 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -12,6 +12,9 @@ #include "ieee80211_i.h" #include "mesh.h" +#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) +#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) + #define PP_OFFSET 1 /* Path Selection Protocol */ #define PM_OFFSET 5 /* Path Selection Metric */ #define CC_OFFSET 9 /* Congestion Control Mode */ @@ -35,6 +38,16 @@ void ieee80211s_stop(void) kmem_cache_destroy(rm_cache); } +static void ieee80211_mesh_housekeeping_timer(unsigned long data) +{ + struct ieee80211_sub_if_data *sdata = (void *) data; + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + ifmsh->housekeeping = true; + queue_work(local->hw.workqueue, &ifmsh->work); +} + /** * mesh_matches_local - check if the config of a mesh point matches ours * @@ -46,7 +59,7 @@ void ieee80211s_stop(void) */ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *sta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; /* * As support for each feature is added, check for matching @@ -58,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat * - MDA enabled * - Power management control on fc */ - if (sta->mesh_id_len == ie->mesh_id_len && - memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && - memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && - memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && - memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) + if (ifmsh->mesh_id_len == ie->mesh_id_len && + memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && + memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && + memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && + memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) return true; return false; @@ -95,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) */ free_plinks = mesh_plink_availables(sdata); - if (free_plinks != sdata->u.sta.accepting_plinks) - ieee80211_sta_timer((unsigned long) sdata); + if (free_plinks != sdata->u.mesh.accepting_plinks) + ieee80211_mesh_housekeeping_timer((unsigned long) sdata); } -void mesh_ids_set_default(struct ieee80211_if_sta *sta) +void mesh_ids_set_default(struct ieee80211_if_mesh *sta) { u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; @@ -112,22 +125,22 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) { int i; - sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); - if (!sdata->u.sta.rmc) + sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); + if (!sdata->u.mesh.rmc) return -ENOMEM; - sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; + sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; for (i = 0; i < RMC_BUCKETS; i++) - INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); + INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); return 0; } void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) { - struct mesh_rmc *rmc = sdata->u.sta.rmc; + struct mesh_rmc *rmc = sdata->u.mesh.rmc; struct rmc_entry *p, *n; int i; - if (!sdata->u.sta.rmc) + if (!sdata->u.mesh.rmc) return; for (i = 0; i < RMC_BUCKETS; i++) @@ -137,7 +150,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) } kfree(rmc); - sdata->u.sta.rmc = NULL; + sdata->u.mesh.rmc = NULL; } /** @@ -155,7 +168,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, struct ieee80211_sub_if_data *sdata) { - struct mesh_rmc *rmc = sdata->u.sta.rmc; + struct mesh_rmc *rmc = sdata->u.mesh.rmc; u32 seqnum = 0; int entries = 0; u8 idx; @@ -217,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) } } - pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); + pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); *pos++ = WLAN_EID_MESH_ID; - *pos++ = sdata->u.sta.mesh_id_len; - if (sdata->u.sta.mesh_id_len) - memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len); + *pos++ = sdata->u.mesh.mesh_id_len; + if (sdata->u.mesh.mesh_id_len) + memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); pos = skb_put(skb, 21); *pos++ = WLAN_EID_MESH_CONFIG; @@ -230,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) *pos++ = 1; /* Active path selection protocol ID */ - memcpy(pos, sdata->u.sta.mesh_pp_id, 4); + memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); pos += 4; /* Active path selection metric ID */ - memcpy(pos, sdata->u.sta.mesh_pm_id, 4); + memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); pos += 4; /* Congestion control mode identifier */ - memcpy(pos, sdata->u.sta.mesh_cc_id, 4); + memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); pos += 4; /* Channel precedence: @@ -248,8 +261,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) pos += 4; /* Mesh capability */ - sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); - *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; + sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); + *pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00; *pos++ = 0x00; return; @@ -337,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = wdev_priv(&sdata->wdev); - queue_work(local->hw.workqueue, &ifsta->work); + queue_work(local->hw.workqueue, &ifmsh->work); } struct mesh_table *mesh_table_grow(struct mesh_table *tbl) @@ -392,50 +405,255 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, struct ieee80211_sub_if_data *sdata) { meshhdr->flags = 0; - meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; - put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); - sdata->u.sta.mesh_seqnum++; + meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; + put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); + sdata->u.mesh.mesh_seqnum++; return 6; } +static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_mesh *ifmsh) +{ + bool free_plinks; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: running mesh housekeeping\n", + sdata->dev->name); +#endif + + ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); + mesh_path_expire(sdata); + + free_plinks = mesh_plink_availables(sdata); + if (free_plinks != sdata->u.mesh.accepting_plinks) + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + + ifmsh->housekeeping = false; + mod_timer(&ifmsh->housekeeping_timer, + round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); +} + + +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_local *local = sdata->local; + + ifmsh->housekeeping = true; + queue_work(local->hw.workqueue, &ifmsh->work); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); +} + +void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) +{ + del_timer_sync(&sdata->u.mesh.housekeeping_timer); + /* + * When we get here, the interface is marked down. + * Call synchronize_rcu() to wait for the RX path + * should it be using the interface and enqueuing + * frames at this very time on another CPU. + */ + synchronize_rcu(); + skb_queue_purge(&sdata->u.mesh.skb_queue); +} + +static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + u16 stype, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_local *local= sdata->local; + struct ieee802_11_elems elems; + struct ieee80211_channel *channel; + u64 supp_rates = 0; + size_t baselen; + int freq; + enum ieee80211_band band = rx_status->band; + + /* ignore ProbeResp to foreign address */ + if (stype == IEEE80211_STYPE_PROBE_RESP && + compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) + return; + + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; + if (baselen > len) + return; + + ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, + &elems); + + if (elems.ds_params && elems.ds_params_len == 1) + freq = ieee80211_channel_to_frequency(elems.ds_params[0]); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(local->hw.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) + return; + + if (elems.mesh_id && elems.mesh_config && + mesh_matches_local(&elems, sdata)) { + supp_rates = ieee80211_sta_get_rates(local, &elems, band); + + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, + mesh_peer_accepts_plinks(&elems)); + } +} + +static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee80211_rx_status *rx_status) +{ + switch (mgmt->u.action.category) { + case PLINK_CATEGORY: + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); + break; + case MESH_PATH_SEL_CATEGORY: + mesh_rx_path_sel_frame(sdata, mgmt, len); + break; + } +} + +static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status; + struct ieee80211_if_mesh *ifmsh; + struct ieee80211_mgmt *mgmt; + u16 stype; + + ifmsh = &sdata->u.mesh; + + rx_status = (struct ieee80211_rx_status *) skb->cb; + mgmt = (struct ieee80211_mgmt *) skb->data; + stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; + + switch (stype) { + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, + rx_status); + break; + case IEEE80211_STYPE_ACTION: + ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); + break; + } + + kfree_skb(skb); +} + +static void ieee80211_mesh_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, u.mesh.work); + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct sk_buff *skb; + + if (!netif_running(sdata->dev)) + return; + + if (local->sta_sw_scanning || local->sta_hw_scanning) + return; + + while ((skb = skb_dequeue(&ifmsh->skb_queue))) + ieee80211_mesh_rx_queued_mgmt(sdata, skb); + + if (ifmsh->preq_queue_len && + time_after(jiffies, + ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) + mesh_path_start_discovery(sdata); + + if (ifmsh->housekeeping) + ieee80211_mesh_housekeeping(sdata, ifmsh); +} + +void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + if (ieee80211_vif_is_mesh(&sdata->vif)) + queue_work(local->hw.workqueue, &sdata->u.mesh.work); + rcu_read_unlock(); +} + void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - - ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; - ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; - ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; - ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; - ifsta->mshcfg.dot11MeshTTL = MESH_TTL; - ifsta->mshcfg.auto_open_plinks = true; - ifsta->mshcfg.dot11MeshMaxPeerLinks = + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + INIT_WORK(&ifmsh->work, ieee80211_mesh_work); + setup_timer(&ifmsh->housekeeping_timer, + ieee80211_mesh_housekeeping_timer, + (unsigned long) sdata); + skb_queue_head_init(&sdata->u.mesh.skb_queue); + + ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; + ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; + ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; + ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; + ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; + ifmsh->mshcfg.auto_open_plinks = true; + ifmsh->mshcfg.dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS; - ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = + ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT; - ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = + ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT; - ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = + ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME; - ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = + ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES; - ifsta->mshcfg.path_refresh_time = + ifmsh->mshcfg.path_refresh_time = MESH_PATH_REFRESH_TIME; - ifsta->mshcfg.min_discovery_timeout = + ifmsh->mshcfg.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT; - ifsta->accepting_plinks = true; - ifsta->preq_id = 0; - ifsta->dsn = 0; - atomic_set(&ifsta->mpaths, 0); + ifmsh->accepting_plinks = true; + ifmsh->preq_id = 0; + ifmsh->dsn = 0; + atomic_set(&ifmsh->mpaths, 0); mesh_rmc_init(sdata); - ifsta->last_preq = jiffies; + ifmsh->last_preq = jiffies; /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) ieee80211s_init(); - mesh_ids_set_default(ifsta); - setup_timer(&ifsta->mesh_path_timer, + mesh_ids_set_default(ifmsh); + setup_timer(&ifmsh->mesh_path_timer, ieee80211_mesh_path_timer, (unsigned long) sdata); - INIT_LIST_HEAD(&ifsta->preq_queue.list); - spin_lock_init(&ifsta->mesh_preq_queue_lock); + INIT_LIST_HEAD(&ifmsh->preq_queue.list); + spin_lock_init(&ifmsh->mesh_preq_queue_lock); +} + +ieee80211_rx_result +ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_mgmt *mgmt; + u16 fc; + + if (skb->len < 24) + return RX_DROP_MONITOR; + + mgmt = (struct ieee80211_mgmt *) skb->data; + fc = le16_to_cpu(mgmt->frame_control); + + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + case IEEE80211_STYPE_ACTION: + memcpy(skb->cb, rx_status, sizeof(*rx_status)); + skb_queue_tail(&ifmsh->skb_queue, skb); + queue_work(local->hw.workqueue, &ifmsh->work); + return RX_QUEUED; + } + + return RX_CONTINUE; } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 84ff5d828fdb..8ee414a0447c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -206,7 +206,7 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, struct ieee80211_sub_if_data *sdata); bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata); -void mesh_ids_set_default(struct ieee80211_if_sta *sta); +void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); @@ -214,6 +214,11 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); void ieee80211s_stop(void); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); +ieee80211_rx_result +ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status); +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); +void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ int mesh_nexthop_lookup(struct sk_buff *skb, @@ -269,8 +274,8 @@ extern int mesh_allocated; static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) { - return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks - - atomic_read(&sdata->u.sta.mshstats.estab_plinks); + return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - + atomic_read(&sdata->u.mesh.mshstats.estab_plinks); } static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) @@ -288,8 +293,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath) for (i = 0; i <= x->hash_mask; i++) \ hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) +void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); + #else #define mesh_allocated 0 +static inline void +ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} #endif #endif /* IEEE80211S_H */ diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 210d6b852406..1fad792ad258 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -64,14 +64,14 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) #define net_traversal_jiffies(s) \ - msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) + msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) #define default_lifetime(s) \ - MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout) + MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout) #define min_preq_int_jiff(s) \ - (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval)) -#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries) + (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval)) +#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries) #define disc_timeout_jiff(s) \ - msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout) + msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout) enum mpath_frame_type { MPATH_PREQ = 0, @@ -395,7 +395,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_path *mpath; u8 *dst_addr, *orig_addr; u8 dst_flags, ttl; @@ -414,11 +414,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, forward = false; reply = true; metric = 0; - if (time_after(jiffies, ifsta->last_dsn_update + + if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || - time_before(jiffies, ifsta->last_dsn_update)) { - dst_dsn = ++ifsta->dsn; - ifsta->last_dsn_update = jiffies; + time_before(jiffies, ifmsh->last_dsn_update)) { + dst_dsn = ++ifmsh->dsn; + ifmsh->last_dsn_update = jiffies; } } else { rcu_read_lock(); @@ -444,7 +444,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, if (reply) { lifetime = PREQ_IE_LIFETIME(preq_elem); - ttl = ifsta->mshcfg.dot11MeshTTL; + ttl = ifmsh->mshcfg.dot11MeshTTL; if (ttl != 0) mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, cpu_to_le32(dst_dsn), 0, orig_addr, @@ -452,7 +452,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, cpu_to_le32(lifetime), cpu_to_le32(metric), 0, sdata); else - ifsta->mshstats.dropped_frames_ttl++; + ifmsh->mshstats.dropped_frames_ttl++; } if (forward) { @@ -462,7 +462,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ttl = PREQ_IE_TTL(preq_elem); lifetime = PREQ_IE_LIFETIME(preq_elem); if (ttl <= 1) { - ifsta->mshstats.dropped_frames_ttl++; + ifmsh->mshstats.dropped_frames_ttl++; return; } --ttl; @@ -475,7 +475,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), cpu_to_le32(preq_id), sdata); - ifsta->mshstats.fwded_frames++; + ifmsh->mshstats.fwded_frames++; } } @@ -503,7 +503,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, ttl = PREP_IE_TTL(prep_elem); if (ttl <= 1) { - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; return; } @@ -533,12 +533,12 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, cpu_to_le32(lifetime), cpu_to_le32(metric), 0, sdata); rcu_read_unlock(); - sdata->u.sta.mshstats.fwded_frames++; + sdata->u.mesh.mshstats.fwded_frames++; return; fail: rcu_read_unlock(); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; return; } @@ -631,7 +631,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) { struct ieee80211_sub_if_data *sdata = mpath->sdata; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); @@ -640,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) return; } - spin_lock(&ifsta->mesh_preq_queue_lock); - if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { - spin_unlock(&ifsta->mesh_preq_queue_lock); + spin_lock(&ifmsh->mesh_preq_queue_lock); + if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { + spin_unlock(&ifmsh->mesh_preq_queue_lock); kfree(preq_node); if (printk_ratelimit()) printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); @@ -652,21 +652,21 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) memcpy(preq_node->dst, mpath->dst, ETH_ALEN); preq_node->flags = flags; - list_add_tail(&preq_node->list, &ifsta->preq_queue.list); - ++ifsta->preq_queue_len; - spin_unlock(&ifsta->mesh_preq_queue_lock); + list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); + ++ifmsh->preq_queue_len; + spin_unlock(&ifmsh->mesh_preq_queue_lock); - if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata))) - queue_work(sdata->local->hw.workqueue, &ifsta->work); + if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) + queue_work(sdata->local->hw.workqueue, &ifmsh->work); - else if (time_before(jiffies, ifsta->last_preq)) { + else if (time_before(jiffies, ifmsh->last_preq)) { /* avoid long wait if did not send preqs for a long time * and jiffies wrapped around */ - ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; - queue_work(sdata->local->hw.workqueue, &ifsta->work); + ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; + queue_work(sdata->local->hw.workqueue, &ifmsh->work); } else - mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + + mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + min_preq_int_jiff(sdata)); } @@ -677,25 +677,25 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) */ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; struct mesh_path *mpath; u8 ttl, dst_flags; u32 lifetime; - spin_lock(&ifsta->mesh_preq_queue_lock); - if (!ifsta->preq_queue_len || - time_before(jiffies, ifsta->last_preq + + spin_lock(&ifmsh->mesh_preq_queue_lock); + if (!ifmsh->preq_queue_len || + time_before(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) { - spin_unlock(&ifsta->mesh_preq_queue_lock); + spin_unlock(&ifmsh->mesh_preq_queue_lock); return; } - preq_node = list_first_entry(&ifsta->preq_queue.list, + preq_node = list_first_entry(&ifmsh->preq_queue.list, struct mesh_preq_queue, list); list_del(&preq_node->list); - --ifsta->preq_queue_len; - spin_unlock(&ifsta->mesh_preq_queue_lock); + --ifmsh->preq_queue_len; + spin_unlock(&ifmsh->mesh_preq_queue_lock); rcu_read_lock(); mpath = mesh_path_lookup(preq_node->dst, sdata); @@ -720,18 +720,18 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) goto enddiscovery; } - ifsta->last_preq = jiffies; + ifmsh->last_preq = jiffies; - if (time_after(jiffies, ifsta->last_dsn_update + + if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || - time_before(jiffies, ifsta->last_dsn_update)) { - ++ifsta->dsn; - sdata->u.sta.last_dsn_update = jiffies; + time_before(jiffies, ifmsh->last_dsn_update)) { + ++ifmsh->dsn; + sdata->u.mesh.last_dsn_update = jiffies; } lifetime = default_lifetime(sdata); - ttl = sdata->u.sta.mshcfg.dot11MeshTTL; + ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; if (ttl == 0) { - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } @@ -743,10 +743,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) spin_unlock_bh(&mpath->state_lock); mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, - cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, + cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, ttl, cpu_to_le32(lifetime), 0, - cpu_to_le32(ifsta->preq_id++), sdata); + cpu_to_le32(ifmsh->preq_id++), sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: @@ -783,7 +783,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { dev_kfree_skb(skb); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; err = -ENOSPC; goto endlookup; } @@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, mpath->exp_time - - msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) + msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0a60f55f32ab..e4fa2905fadc 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -153,7 +153,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) if (is_multicast_ether_addr(dst)) return -ENOTSUPP; - if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) + if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) return -ENOSPC; err = -ENOMEM; @@ -221,7 +221,7 @@ err_exists: err_node_alloc: kfree(new_mpath); err_path_alloc: - atomic_dec(&sdata->u.sta.mpaths); + atomic_dec(&sdata->u.mesh.mpaths); return err; } @@ -306,7 +306,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) struct ieee80211_sub_if_data *sdata = node->mpath->sdata; del_timer_sync(&node->mpath->timer); - atomic_dec(&sdata->u.sta.mpaths); + atomic_dec(&sdata->u.mesh.mpaths); kfree(node->mpath); kfree(node); } @@ -401,7 +401,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, } kfree_skb(skb); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; } /** diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7356462dee96..990a4b7f6bcc 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -36,11 +36,11 @@ #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 #define MESH_SECURITY_FAILED_VERIFICATION 10 -#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries) -#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout) -#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout) -#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout) -#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks) +#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) +#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) +#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) +#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) +#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) enum plink_frame_type { PLINK_OPEN = 0, @@ -63,14 +63,14 @@ enum plink_event { static inline void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { - atomic_inc(&sdata->u.sta.mshstats.estab_plinks); + atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); mesh_accept_plinks_update(sdata); } static inline void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) { - atomic_dec(&sdata->u.sta.mshstats.estab_plinks); + atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); mesh_accept_plinks_update(sdata); } @@ -245,8 +245,8 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data sta->last_rx = jiffies; sta->supp_rates[local->hw.conf.channel->band] = rates; if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && - sdata->u.sta.accepting_plinks && - sdata->u.sta.mshcfg.auto_open_plinks) + sdata->u.mesh.accepting_plinks && + sdata->u.mesh.mshcfg.auto_open_plinks) mesh_plink_open(sta); rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ef73f8953724..9e20a0c20a46 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -22,11 +22,11 @@ #include #include #include +#include #include "ieee80211_i.h" #include "rate.h" #include "led.h" -#include "mesh.h" #define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 #define IEEE80211_AUTH_TIMEOUT (HZ / 5) @@ -34,7 +34,6 @@ #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) #define IEEE80211_ASSOC_MAX_TRIES 3 #define IEEE80211_MONITORING_INTERVAL (2 * HZ) -#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) #define IEEE80211_PROBE_INTERVAL (60 * HZ) #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) #define IEEE80211_SCAN_INTERVAL (2 * HZ) @@ -43,7 +42,6 @@ #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) -#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 @@ -1508,14 +1506,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) return; - if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && - elems->mesh_config && mesh_matches_local(elems, sdata)) { - supp_rates = ieee80211_sta_get_rates(local, elems, band); - - mesh_neighbour_update(mgmt->sa, supp_rates, sdata, - mesh_peer_accepts_plinks(elems)); - } - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { supp_rates = ieee80211_sta_get_rates(local, elems, band); @@ -1785,26 +1775,6 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb, 0); } -static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - /* currently we only handle mesh interface action frames here */ - if (!ieee80211_vif_is_mesh(&sdata->vif)) - return; - - switch (mgmt->u.action.category) { - case PLINK_CATEGORY: - mesh_rx_plink_frame(sdata, mgmt, len, rx_status); - break; - case MESH_PATH_SEL_CATEGORY: - mesh_rx_path_sel_frame(sdata, mgmt, len); - break; - } -} - void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { @@ -1825,7 +1795,6 @@ void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff * case IEEE80211_STYPE_PROBE_REQ: case IEEE80211_STYPE_PROBE_RESP: case IEEE80211_STYPE_BEACON: - case IEEE80211_STYPE_ACTION: memcpy(skb->cb, rx_status, sizeof(*rx_status)); case IEEE80211_STYPE_AUTH: case IEEE80211_STYPE_ASSOC_RESP: @@ -1881,9 +1850,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, case IEEE80211_STYPE_DISASSOC: ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); break; - case IEEE80211_STYPE_ACTION: - ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status); - break; } kfree_skb(skb); @@ -1928,35 +1894,6 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, } -#ifdef CONFIG_MAC80211_MESH -static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - bool free_plinks; - - ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); - mesh_path_expire(sdata); - - free_plinks = mesh_plink_availables(sdata); - if (free_plinks != sdata->u.sta.accepting_plinks) - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); - - mod_timer(&ifsta->timer, jiffies + - IEEE80211_MESH_HOUSEKEEPING_INTERVAL); -} - - -void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_sta *ifsta; - ifsta = &sdata->u.sta; - ifsta->state = IEEE80211_STA_MLME_MESH_UP; - ieee80211_sta_timer((unsigned long)sdata); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); -} -#endif - - void ieee80211_sta_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = @@ -2524,21 +2461,13 @@ void ieee80211_sta_work(struct work_struct *work) return; if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) + sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) return; ifsta = &sdata->u.sta; while ((skb = skb_dequeue(&ifsta->skb_queue))) ieee80211_sta_rx_queued_mgmt(sdata, skb); -#ifdef CONFIG_MAC80211_MESH - if (ifsta->preq_queue_len && - time_after(jiffies, - ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) - mesh_path_start_discovery(sdata); -#endif - if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && @@ -2575,11 +2504,6 @@ void ieee80211_sta_work(struct work_struct *work) case IEEE80211_STA_MLME_IBSS_JOINED: ieee80211_sta_merge_ibss(sdata, ifsta); break; -#ifdef CONFIG_MAC80211_MESH - case IEEE80211_STA_MLME_MESH_UP: - ieee80211_mesh_housekeeping(sdata, ifsta); - break; -#endif default: WARN_ON(1); break; @@ -2596,8 +2520,7 @@ void ieee80211_sta_work(struct work_struct *work) static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - ieee80211_vif_is_mesh(&sdata->vif)) + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) queue_work(sdata->local->hw.workqueue, &sdata->u.sta.work); } diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a914ba73ccf5..21e1942ea975 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -148,9 +148,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, struct ieee80211_local *local, struct sta_info *sta) { -#ifdef CONFIG_MAC80211_MESH struct ieee80211_sub_if_data *sdata = sta->sdata; -#endif struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; struct rc_pid_rateinfo *rinfo = pinfo->rinfo; struct ieee80211_supported_band *sband; @@ -181,11 +179,8 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, pf = spinfo->last_pf; else { pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; -#ifdef CONFIG_MAC80211_MESH - if (pf == 100 && - sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) + if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) mesh_plink_broken(sta); -#endif pf <<= RC_PID_ARITH_SHIFT; sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) >> RC_PID_ARITH_SHIFT; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d0803797902b..208563a27bc4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1404,7 +1404,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (rx->flags & IEEE80211_RX_RA_MATCH) { if (!mesh_hdr->ttl) - IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, + IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, dropped_frames_ttl); else { struct ieee80211_hdr *fwd_hdr; @@ -1591,9 +1591,11 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; + if (ieee80211_vif_is_mesh(&sdata->vif)) + return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); + if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return RX_DROP_MONITOR; if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f8b296bed0b9..f4399e9ac928 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -476,6 +476,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) done: ieee80211_mlme_notify_scan_completed(local); + ieee80211_mesh_notify_scan_completed(local); } EXPORT_SYMBOL(ieee80211_scan_completed); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c413d4836afe..1059b17c83b0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1330,7 +1330,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (mesh_nexthop_lookup(skb, osdata)) return 0; if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) - IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, + IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, fwded_frames); } } @@ -1483,9 +1483,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); - if (!sdata->u.sta.mshcfg.dot11MeshTTL) { + if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { /* Do not send frames with mesh_ttl == 0 */ - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; ret = 0; goto fail; } @@ -1815,10 +1815,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct rate_selection rsel; struct beacon_data *beacon; struct ieee80211_supported_band *sband; - struct ieee80211_mgmt *mgmt; int *num_beacons; enum ieee80211_band band = local->hw.conf.channel->band; - u8 *pos; sband = local->hw.wiphy->bands[band]; @@ -1885,7 +1883,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, IEEE80211_STYPE_BEACON); num_beacons = &ifsta->num_beacons; +#ifdef CONFIG_MAC80211_MESH } else if (ieee80211_vif_is_mesh(&sdata->vif)) { + struct ieee80211_mgmt *mgmt; + u8 *pos; + /* headroom, head length, tail length and maximum TIM length */ skb = dev_alloc_skb(local->tx_headroom + 400); if (!skb) @@ -1910,7 +1912,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, mesh_mgmt_ies_add(skb, sdata); - num_beacons = &sdata->u.sta.num_beacons; + num_beacons = &sdata->u.mesh.num_beacons; +#endif } else { WARN_ON(1); goto out; -- cgit v1.2.3 From b7413430d4d2a6168e68231d9f93763047b6d60c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:50 +0200 Subject: mac80211: fix work race When we stop an interface, the work on it may still be pending or running. We do cancel the timer, but we do not currently protect against the work struct. The race is very unlikely to hit -- it'll happen only when the driver is using mac80211's workqueue to run long-running tasks and the sta/mesh works are delayed for quite a bit. This patch fixes it by cancelling the work explicitly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 8 ++++++++ net/mac80211/mesh.c | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 522fe6176485..ebdec7106d63 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -547,6 +547,14 @@ static int ieee80211_stop(struct net_device *dev) sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; memset(sdata->u.sta.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.sta.timer); + /* + * If the timer fired while we waited for it, it will have + * requeued the work. Now the work will be running again + * but will not rearm the timer again because it checks + * whether the interface is running, which, at this point, + * it no longer is. + */ + cancel_work_sync(&sdata->u.sta.work); /* * When we get here, the interface is marked down. * Call synchronize_rcu() to wait for the RX path diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9e47725cc592..a0141f5ff184 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -448,6 +448,15 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) { del_timer_sync(&sdata->u.mesh.housekeeping_timer); + /* + * If the timer fired while we waited for it, it will have + * requeued the work. Now the work will be running again + * but will not rearm the timer again because it checks + * whether the interface is running, which, at this point, + * it no longer is. + */ + cancel_work_sync(&sdata->u.mesh.work); + /* * When we get here, the interface is marked down. * Call synchronize_rcu() to wait for the RX path -- cgit v1.2.3 From 5bc75728fd43bb15b46f16ef465bcf9d487393cf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:51 +0200 Subject: mac80211: fix scan vs. interface removal race When we remove an interface, we can currently end up having a pointer to it left in local->scan_sdata after it has been set down, and then with a hardware scan the scan completion can try to access it which is a bug. Alternatively, a scan that started as a hardware scan may terminate as though it was a software scan, if the timing is just right. On SMP systems, software scan also has a similar problem, just canceling the delayed work and setting a flag isn't enough since it may be running concurrently; in this case we would also never restore state of other interfaces. This patch hopefully fixes the problems by always invoking ieee80211_scan_completed or requiring it to be invoked by the driver, I suspect the drivers that have ->hw_scan() are buggy. The bug will not manifest itself unless you remove the interface while hw-scanning which will also turn off the hw, and then add a new interface which will be unusable until you scan once. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 +++- net/mac80211/main.c | 33 +++++++++++++++++++++++++-------- net/mac80211/mlme.c | 2 +- net/mac80211/scan.c | 38 +++++++++++++++++++++++++++----------- 4 files changed, 56 insertions(+), 21 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f504e3eca7d3..d67882dd3604 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1124,7 +1124,9 @@ enum ieee80211_ampdu_mlme_action { * @hw_scan: Ask the hardware to service the scan request, no need to start * the scan state machine in stack. The scan must honour the channel * configuration done by the regulatory agent in the wiphy's registered - * bands. + * bands. When the scan finishes, ieee80211_scan_completed() must be + * called; note that it also must be called when the scan cannot finish + * because the hardware is turned off! Anything else is a bug! * * @get_stats: return low-level statistics * diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ebdec7106d63..4bfac4b41c51 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -564,14 +564,6 @@ static int ieee80211_stop(struct net_device *dev) synchronize_rcu(); skb_queue_purge(&sdata->u.sta.skb_queue); - if (local->scan_sdata == sdata) { - if (!local->ops->hw_scan) { - local->sta_sw_scanning = 0; - cancel_delayed_work(&local->scan_work); - } else - local->sta_hw_scanning = 0; - } - sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; kfree(sdata->u.sta.extra_ie); sdata->u.sta.extra_ie = NULL; @@ -585,6 +577,31 @@ static int ieee80211_stop(struct net_device *dev) } /* fall through */ default: + if (local->scan_sdata == sdata) { + if (!local->ops->hw_scan) + cancel_delayed_work_sync(&local->scan_work); + /* + * The software scan can no longer run now, so we can + * clear out the scan_sdata reference. However, the + * hardware scan may still be running. The complete + * function must be prepared to handle a NULL value. + */ + local->scan_sdata = NULL; + /* + * The memory barrier guarantees that another CPU + * that is hardware-scanning will now see the fact + * that this interface is gone. + */ + smp_mb(); + /* + * If software scanning, complete the scan but since + * the scan_sdata is NULL already don't send out a + * scan event to userspace -- the scan is incomplete. + */ + if (local->sta_sw_scanning) + ieee80211_scan_completed(&local->hw); + } + conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = dev->dev_addr; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9e20a0c20a46..19c7f21e49d1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2530,7 +2530,7 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) struct ieee80211_sub_if_data *sdata = local->scan_sdata; struct ieee80211_if_sta *ifsta; - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata && sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f4399e9ac928..27727027d76d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -430,9 +430,20 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) struct ieee80211_sub_if_data *sdata; union iwreq_data wrqu; + if (WARN_ON(!local->sta_hw_scanning && !local->sta_sw_scanning)) + return; + local->last_scan_completed = jiffies; memset(&wrqu, 0, sizeof(wrqu)); - wireless_send_event(local->scan_sdata->dev, SIOCGIWSCAN, &wrqu, NULL); + + /* + * local->scan_sdata could have been NULLed by the interface + * down code in case we were scanning on an interface that is + * being taken down. + */ + sdata = local->scan_sdata; + if (sdata) + wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); if (local->sta_hw_scanning) { local->sta_hw_scanning = 0; @@ -491,7 +502,10 @@ void ieee80211_sta_scan_work(struct work_struct *work) int skip; unsigned long next_delay = 0; - if (!local->sta_sw_scanning) + /* + * Avoid re-scheduling when the sdata is going away. + */ + if (!netif_running(sdata->dev)) return; switch (local->scan_state) { @@ -570,9 +584,8 @@ void ieee80211_sta_scan_work(struct work_struct *work) break; } - if (local->sta_sw_scanning) - queue_delayed_work(local->hw.workqueue, &local->scan_work, - next_delay); + queue_delayed_work(local->hw.workqueue, &local->scan_work, + next_delay); } @@ -609,13 +622,16 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, } if (local->ops->hw_scan) { - int rc = local->ops->hw_scan(local_to_hw(local), - ssid, ssid_len); - if (!rc) { - local->sta_hw_scanning = 1; - local->scan_sdata = scan_sdata; + int rc; + + local->sta_hw_scanning = 1; + rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); + if (rc) { + local->sta_hw_scanning = 0; + return rc; } - return rc; + local->scan_sdata = scan_sdata; + return 0; } local->sta_sw_scanning = 1; -- cgit v1.2.3 From 9c6bd79011b14a8bfe58aad0acfb51e4dca05eed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:52 +0200 Subject: mac80211: reorder MLME code more This way all the utility functions are at the top, then the state machine and externally callable functions are moved to the bottom. Also clean up ieee80211_i.h a bit and add a few comments about which functions are called from where. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 39 +-- net/mac80211/iface.c | 17 +- net/mac80211/mlme.c | 700 +++++++++++++++++++++++---------------------- 3 files changed, 384 insertions(+), 372 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cac0b1334548..442a43a34005 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -882,54 +882,53 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) } -/* ieee80211.c */ int ieee80211_hw_config(struct ieee80211_local *local); int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_info *req_ht_cap, struct ieee80211_ht_bss_info *req_bss_cap); +void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, + u32 changed); -/* ieee80211_ioctl.c */ +/* wireless extensions */ extern const struct iw_handler_def ieee80211_iw_handler_def; int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); -/* ieee80211_sta.c */ -void ieee80211_sta_timer(unsigned long data); -void ieee80211_sta_work(struct work_struct *work); +/* STA/IBSS code */ +void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_scan_work(struct work_struct *work); void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); -int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); -int ieee80211_sta_scan_results(struct ieee80211_local *local, - struct iw_request_info *info, - char *buf, size_t len); -ieee80211_rx_result ieee80211_sta_rx_scan( - struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status); -void ieee80211_rx_bss_list_init(struct ieee80211_local *local); -void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); -int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates); int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); -void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - u32 changed); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); u64 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); -void ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems); + +/* scan/BSS handling */ +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); +int ieee80211_sta_scan_results(struct ieee80211_local *local, + struct iw_request_info *info, + char *buf, size_t len); +ieee80211_rx_result ieee80211_sta_rx_scan( + struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status); +void ieee80211_rx_bss_list_init(struct ieee80211_local *local); +void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); + void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, u8 *ssid, size_t ssid_len); @@ -1007,6 +1006,8 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); +void ieee802_11_parse_elems(u8 *start, size_t len, + struct ieee802_11_elems *elems); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ddbaa417e2ec..61b19340488c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -83,8 +83,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev) static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, enum ieee80211_if_types type) { - struct ieee80211_if_sta *ifsta; - /* clear type-dependent union */ memset(&sdata->u, 0, sizeof(sdata->u)); @@ -101,20 +99,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: - ifsta = &sdata->u.sta; - INIT_WORK(&ifsta->work, ieee80211_sta_work); - setup_timer(&ifsta->timer, ieee80211_sta_timer, - (unsigned long) sdata); - skb_queue_head_init(&ifsta->skb_queue); - - ifsta->capab = WLAN_CAPABILITY_ESS; - ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | - IEEE80211_AUTH_ALG_SHARED_KEY; - ifsta->flags |= IEEE80211_STA_CREATE_IBSS | - IEEE80211_STA_AUTO_BSSID_SEL | - IEEE80211_STA_AUTO_CHANNEL_SEL; - if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) - ifsta->flags |= IEEE80211_STA_WMM_ENABLED; + ieee80211_sta_setup_sdata(sdata); break; case IEEE80211_IF_TYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 19c7f21e49d1..e14830106526 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -93,44 +93,46 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, return count; } -/* frame sending functions */ -static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, - int transaction, u8 *extra, size_t extra_len, - int encrypt) +/* also used by mesh code */ +u64 ieee80211_sta_get_rates(struct ieee80211_local *local, + struct ieee802_11_elems *elems, + enum ieee80211_band band) { - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; + struct ieee80211_supported_band *sband; + struct ieee80211_rate *bitrates; + size_t num_rates; + u64 supp_rates; + int i, j; + sband = local->hw.wiphy->bands[band]; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 6 + extra_len); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", sdata->dev->name); - return; + if (!sband) { + WARN_ON(1); + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; } - skb_reserve(skb, local->hw.extra_tx_headroom); - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); - memset(mgmt, 0, 24 + 6); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_AUTH); - if (encrypt) - mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); - mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); - ifsta->auth_transaction = transaction + 1; - mgmt->u.auth.status_code = cpu_to_le16(0); - if (extra) - memcpy(skb_put(skb, extra_len), extra, extra_len); - ieee80211_tx_skb(sdata, skb, encrypt); + bitrates = sband->bitrates; + num_rates = sband->n_bitrates; + supp_rates = 0; + for (i = 0; i < elems->supp_rates_len + + elems->ext_supp_rates_len; i++) { + u8 rate = 0; + int own_rate; + if (i < elems->supp_rates_len) + rate = elems->supp_rates[i]; + else if (elems->ext_supp_rates) + rate = elems->ext_supp_rates + [i - elems->supp_rates_len]; + own_rate = 5 * (rate & 0x7f); + for (j = 0; j < num_rates; j++) + if (bitrates[j].bitrate == own_rate) + supp_rates |= BIT(j); + } + return supp_rates; } +/* frame sending functions */ + +/* also used by scanning code */ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len) { @@ -191,6 +193,43 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ieee80211_tx_skb(sdata, skb, 0); } +static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta, + int transaction, u8 *extra, size_t extra_len, + int encrypt) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + 6 + extra_len); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for auth " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); + memset(mgmt, 0, 24 + 6); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_AUTH); + if (encrypt) + mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); + mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); + mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); + ifsta->auth_transaction = transaction + 1; + mgmt->u.auth.status_code = cpu_to_le16(0); + if (extra) + memcpy(skb_put(skb, extra_len), extra, extra_len); + + ieee80211_tx_skb(sdata, skb, encrypt); +} + static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { @@ -1414,42 +1453,6 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, return res; } -u64 ieee80211_sta_get_rates(struct ieee80211_local *local, - struct ieee802_11_elems *elems, - enum ieee80211_band band) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_rate *bitrates; - size_t num_rates; - u64 supp_rates; - int i, j; - sband = local->hw.wiphy->bands[band]; - - if (!sband) { - WARN_ON(1); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - } - - bitrates = sband->bitrates; - num_rates = sband->n_bitrates; - supp_rates = 0; - for (i = 0; i < elems->supp_rates_len + - elems->ext_supp_rates_len; i++) { - u8 rate = 0; - int own_rate; - if (i < elems->supp_rates_len) - rate = elems->supp_rates[i]; - else if (elems->ext_supp_rates) - rate = elems->ext_supp_rates - [i - elems->supp_rates_len]; - own_rate = 5 * (rate & 0x7f); - for (j = 0; j < num_rates; j++) - if (bitrates[j].bitrate == own_rate) - supp_rates |= BIT(j); - } - return supp_rates; -} - static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band) { @@ -1894,7 +1897,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, } -void ieee80211_sta_timer(unsigned long data) +static void ieee80211_sta_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; @@ -1937,28 +1940,6 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, } -void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - struct ieee80211_local *local = sdata->local; - - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return; - - if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | - IEEE80211_STA_AUTO_BSSID_SEL)) && - (ifsta->flags & (IEEE80211_STA_SSID_SET | - IEEE80211_STA_AUTO_SSID_SEL))) { - - if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) - ieee80211_set_disassoc(sdata, ifsta, true, true, - WLAN_REASON_DEAUTH_LEAVING); - - set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); - queue_work(local->hw.workqueue, &ifsta->work); - } -} - static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, const char *ssid, int ssid_len) { @@ -2160,113 +2141,190 @@ dont_join: } -int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) { - struct ieee80211_if_sta *ifsta; - int res; + struct ieee80211_local *local = sdata->local; + struct ieee80211_sta_bss *bss, *selected = NULL; + int top_rssi = 0, freq; - if (len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; + spin_lock_bh(&local->sta_bss_lock); + freq = local->oper_channel->center_freq; + list_for_each_entry(bss, &local->sta_bss_list, list) { + if (!(bss->capability & WLAN_CAPABILITY_ESS)) + continue; - ifsta = &sdata->u.sta; + if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | + IEEE80211_STA_AUTO_BSSID_SEL | + IEEE80211_STA_AUTO_CHANNEL_SEL)) && + (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ + !!sdata->default_key)) + continue; - if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { - memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); - memcpy(ifsta->ssid, ssid, len); - ifsta->ssid_len = len; - ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; + if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && + bss->freq != freq) + continue; - res = 0; - /* - * Hack! MLME code needs to be cleaned up to have different - * entry points for configuration and internal selection change - */ - if (netif_running(sdata->dev)) - res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); - if (res) { - printk(KERN_DEBUG "%s: Failed to config new SSID to " - "the low-level driver\n", sdata->dev->name); - return res; - } - } + if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && + memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) + continue; - if (len) - ifsta->flags |= IEEE80211_STA_SSID_SET; - else - ifsta->flags &= ~IEEE80211_STA_SSID_SET; + if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && + !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) + continue; - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && - !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { - ifsta->ibss_join_req = jiffies; - ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; - return ieee80211_sta_find_ibss(sdata, ifsta); + if (!selected || top_rssi < bss->signal) { + selected = bss; + top_rssi = bss->signal; + } } + if (selected) + atomic_inc(&selected->users); + spin_unlock_bh(&local->sta_bss_lock); - return 0; -} - - -int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) -{ - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - memcpy(ssid, ifsta->ssid, ifsta->ssid_len); - *len = ifsta->ssid_len; - return 0; -} - + if (selected) { + ieee80211_set_freq(sdata, selected->freq); + if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) + ieee80211_sta_set_ssid(sdata, selected->ssid, + selected->ssid_len); + ieee80211_sta_set_bssid(sdata, selected->bssid); + ieee80211_sta_def_wmm_params(sdata, selected); -int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) -{ - struct ieee80211_if_sta *ifsta; - int res; + /* Send out direct probe if no probe resp was received or + * the one we have is outdated + */ + if (!selected->last_probe_resp || + time_after(jiffies, selected->last_probe_resp + + IEEE80211_SCAN_RESULT_EXPIRE)) + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + else + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + ieee80211_rx_bss_put(local, selected); + ieee80211_sta_reset_auth(sdata, ifsta); + return 0; + } else { + if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { + ifsta->assoc_scan_tries++; + if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) + ieee80211_sta_start_scan(sdata, NULL, 0); + else + ieee80211_sta_start_scan(sdata, ifsta->ssid, + ifsta->ssid_len); + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); + } else + ifsta->state = IEEE80211_STA_MLME_DISABLED; + } + return -1; +} + + +static void ieee80211_sta_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, u.sta.work); + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_sta *ifsta; + struct sk_buff *skb; + + if (!netif_running(sdata->dev)) + return; + + if (local->sta_sw_scanning || local->sta_hw_scanning) + return; + + if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && + sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) + return; ifsta = &sdata->u.sta; - if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { - memcpy(ifsta->bssid, bssid, ETH_ALEN); - res = 0; - /* - * Hack! See also ieee80211_sta_set_ssid. - */ - if (netif_running(sdata->dev)) - res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); - if (res) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", sdata->dev->name); - return res; - } + while ((skb = skb_dequeue(&ifsta->skb_queue))) + ieee80211_sta_rx_queued_mgmt(sdata, skb); + + if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && + ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && + ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && + test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { + ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); + return; } - if (is_valid_ether_addr(bssid)) - ifsta->flags |= IEEE80211_STA_BSSID_SET; - else - ifsta->flags &= ~IEEE80211_STA_BSSID_SET; + if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { + if (ieee80211_sta_config_auth(sdata, ifsta)) + return; + clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); + } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) + return; - return 0; + switch (ifsta->state) { + case IEEE80211_STA_MLME_DISABLED: + break; + case IEEE80211_STA_MLME_DIRECT_PROBE: + ieee80211_direct_probe(sdata, ifsta); + break; + case IEEE80211_STA_MLME_AUTHENTICATE: + ieee80211_authenticate(sdata, ifsta); + break; + case IEEE80211_STA_MLME_ASSOCIATE: + ieee80211_associate(sdata, ifsta); + break; + case IEEE80211_STA_MLME_ASSOCIATED: + ieee80211_associated(sdata, ifsta); + break; + case IEEE80211_STA_MLME_IBSS_SEARCH: + ieee80211_sta_find_ibss(sdata, ifsta); + break; + case IEEE80211_STA_MLME_IBSS_JOINED: + ieee80211_sta_merge_ibss(sdata, ifsta); + break; + default: + WARN_ON(1); + break; + } + + if (ieee80211_privacy_mismatch(sdata, ifsta)) { + printk(KERN_DEBUG "%s: privacy configuration mismatch and " + "mixed-cell disabled - disassociate\n", sdata->dev->name); + + ieee80211_set_disassoc(sdata, ifsta, false, true, + WLAN_REASON_UNSPECIFIED); + } } +static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) +{ + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) + queue_work(sdata->local->hw.workqueue, + &sdata->u.sta.work); +} -int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) +/* interface setup */ +void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_sta *ifsta; - kfree(ifsta->extra_ie); - if (len == 0) { - ifsta->extra_ie = NULL; - ifsta->extra_ie_len = 0; - return 0; - } - ifsta->extra_ie = kmalloc(len, GFP_KERNEL); - if (!ifsta->extra_ie) { - ifsta->extra_ie_len = 0; - return -ENOMEM; - } - memcpy(ifsta->extra_ie, ie, len); - ifsta->extra_ie_len = len; - return 0; + ifsta = &sdata->u.sta; + INIT_WORK(&ifsta->work, ieee80211_sta_work); + setup_timer(&ifsta->timer, ieee80211_sta_timer, + (unsigned long) sdata); + skb_queue_head_init(&ifsta->skb_queue); + + ifsta->capab = WLAN_CAPABILITY_ESS; + ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | + IEEE80211_AUTH_ALG_SHARED_KEY; + ifsta->flags |= IEEE80211_STA_CREATE_IBSS | + IEEE80211_STA_AUTO_BSSID_SEL | + IEEE80211_STA_AUTO_CHANNEL_SEL; + if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) + ifsta->flags |= IEEE80211_STA_WMM_ENABLED; } - +/* + * Add a new IBSS station, will also be called by the RX code when, + * in IBSS mode, receiving a frame from a yet-unknown station, hence + * must be callable in atomic context. + */ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates) @@ -2312,86 +2370,132 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, return sta; } - -static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) +/* configuration hooks */ +void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss, *selected = NULL; - int top_rssi = 0, freq; - spin_lock_bh(&local->sta_bss_lock); - freq = local->oper_channel->center_freq; - list_for_each_entry(bss, &local->sta_bss_list, list) { - if (!(bss->capability & WLAN_CAPABILITY_ESS)) - continue; + if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + return; - if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | - IEEE80211_STA_AUTO_BSSID_SEL | - IEEE80211_STA_AUTO_CHANNEL_SEL)) && - (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ - !!sdata->default_key)) - continue; + if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | + IEEE80211_STA_AUTO_BSSID_SEL)) && + (ifsta->flags & (IEEE80211_STA_SSID_SET | + IEEE80211_STA_AUTO_SSID_SEL))) { - if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && - bss->freq != freq) - continue; + if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) + ieee80211_set_disassoc(sdata, ifsta, true, true, + WLAN_REASON_DEAUTH_LEAVING); - if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && - memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) - continue; + set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); + queue_work(local->hw.workqueue, &ifsta->work); + } +} - if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && - !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) - continue; +int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) +{ + struct ieee80211_if_sta *ifsta; + int res; - if (!selected || top_rssi < bss->signal) { - selected = bss; - top_rssi = bss->signal; + if (len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + + ifsta = &sdata->u.sta; + + if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { + memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); + memcpy(ifsta->ssid, ssid, len); + ifsta->ssid_len = len; + ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; + + res = 0; + /* + * Hack! MLME code needs to be cleaned up to have different + * entry points for configuration and internal selection change + */ + if (netif_running(sdata->dev)) + res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); + if (res) { + printk(KERN_DEBUG "%s: Failed to config new SSID to " + "the low-level driver\n", sdata->dev->name); + return res; } } - if (selected) - atomic_inc(&selected->users); - spin_unlock_bh(&local->sta_bss_lock); - if (selected) { - ieee80211_set_freq(sdata, selected->freq); - if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) - ieee80211_sta_set_ssid(sdata, selected->ssid, - selected->ssid_len); - ieee80211_sta_set_bssid(sdata, selected->bssid); - ieee80211_sta_def_wmm_params(sdata, selected); + if (len) + ifsta->flags |= IEEE80211_STA_SSID_SET; + else + ifsta->flags &= ~IEEE80211_STA_SSID_SET; - /* Send out direct probe if no probe resp was received or - * the one we have is outdated + if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { + ifsta->ibss_join_req = jiffies; + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; + return ieee80211_sta_find_ibss(sdata, ifsta); + } + + return 0; +} + +int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) +{ + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + memcpy(ssid, ifsta->ssid, ifsta->ssid_len); + *len = ifsta->ssid_len; + return 0; +} + +int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) +{ + struct ieee80211_if_sta *ifsta; + int res; + + ifsta = &sdata->u.sta; + + if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { + memcpy(ifsta->bssid, bssid, ETH_ALEN); + res = 0; + /* + * Hack! See also ieee80211_sta_set_ssid. */ - if (!selected->last_probe_resp || - time_after(jiffies, selected->last_probe_resp - + IEEE80211_SCAN_RESULT_EXPIRE)) - ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; - else - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + if (netif_running(sdata->dev)) + res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); + if (res) { + printk(KERN_DEBUG "%s: Failed to config new BSSID to " + "the low-level driver\n", sdata->dev->name); + return res; + } + } - ieee80211_rx_bss_put(local, selected); - ieee80211_sta_reset_auth(sdata, ifsta); + if (is_valid_ether_addr(bssid)) + ifsta->flags |= IEEE80211_STA_BSSID_SET; + else + ifsta->flags &= ~IEEE80211_STA_BSSID_SET; + + return 0; +} + +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) +{ + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + + kfree(ifsta->extra_ie); + if (len == 0) { + ifsta->extra_ie = NULL; + ifsta->extra_ie_len = 0; return 0; - } else { - if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { - ifsta->assoc_scan_tries++; - if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(sdata, NULL, 0); - else - ieee80211_sta_start_scan(sdata, ifsta->ssid, - ifsta->ssid_len); - ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; - set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); - } else - ifsta->state = IEEE80211_STA_MLME_DISABLED; } - return -1; + ifsta->extra_ie = kmalloc(len, GFP_KERNEL); + if (!ifsta->extra_ie) { + ifsta->extra_ie_len = 0; + return -ENOMEM; + } + memcpy(ifsta->extra_ie, ie, len); + ifsta->extra_ie_len = len; + return 0; } - int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; @@ -2407,7 +2511,6 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason return 0; } - int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; @@ -2425,6 +2528,28 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) return 0; } +/* scan finished notification */ +void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata = local->scan_sdata; + struct ieee80211_if_sta *ifsta; + + if (sdata && sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + ifsta = &sdata->u.sta; + if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || + (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && + !ieee80211_sta_active_ibss(sdata))) + ieee80211_sta_find_ibss(sdata, ifsta); + } + + /* Restart STA timers */ + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + ieee80211_restart_sta_timer(sdata); + rcu_read_unlock(); +} + +/* driver notification call */ void ieee80211_notify_mac(struct ieee80211_hw *hw, enum ieee80211_notification_types notif_type) { @@ -2445,102 +2570,3 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, } } EXPORT_SYMBOL(ieee80211_notify_mac); - -void ieee80211_sta_work(struct work_struct *work) -{ - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, u.sta.work); - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_sta *ifsta; - struct sk_buff *skb; - - if (!netif_running(sdata->dev)) - return; - - if (local->sta_sw_scanning || local->sta_hw_scanning) - return; - - if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) - return; - ifsta = &sdata->u.sta; - - while ((skb = skb_dequeue(&ifsta->skb_queue))) - ieee80211_sta_rx_queued_mgmt(sdata, skb); - - if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && - ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && - ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && - test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { - ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); - return; - } - - if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { - if (ieee80211_sta_config_auth(sdata, ifsta)) - return; - clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); - } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) - return; - - switch (ifsta->state) { - case IEEE80211_STA_MLME_DISABLED: - break; - case IEEE80211_STA_MLME_DIRECT_PROBE: - ieee80211_direct_probe(sdata, ifsta); - break; - case IEEE80211_STA_MLME_AUTHENTICATE: - ieee80211_authenticate(sdata, ifsta); - break; - case IEEE80211_STA_MLME_ASSOCIATE: - ieee80211_associate(sdata, ifsta); - break; - case IEEE80211_STA_MLME_ASSOCIATED: - ieee80211_associated(sdata, ifsta); - break; - case IEEE80211_STA_MLME_IBSS_SEARCH: - ieee80211_sta_find_ibss(sdata, ifsta); - break; - case IEEE80211_STA_MLME_IBSS_JOINED: - ieee80211_sta_merge_ibss(sdata, ifsta); - break; - default: - WARN_ON(1); - break; - } - - if (ieee80211_privacy_mismatch(sdata, ifsta)) { - printk(KERN_DEBUG "%s: privacy configuration mismatch and " - "mixed-cell disabled - disassociate\n", sdata->dev->name); - - ieee80211_set_disassoc(sdata, ifsta, false, true, - WLAN_REASON_UNSPECIFIED); - } -} - -static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) -{ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) - queue_work(sdata->local->hw.workqueue, - &sdata->u.sta.work); -} - -void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) -{ - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - struct ieee80211_if_sta *ifsta; - - if (sdata && sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - ifsta = &sdata->u.sta; - if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && - !ieee80211_sta_active_ibss(sdata))) - ieee80211_sta_find_ibss(sdata, ifsta); - } - - /* Restart STA timers */ - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) - ieee80211_restart_sta_timer(sdata); - rcu_read_unlock(); -} -- cgit v1.2.3 From e16751c3178add97c4f83dcf92e59b536537b22f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:53 +0200 Subject: mac80211: move ieee80211_set_freq to utils It really doesn't belong into the wireless extensions code. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/util.c | 28 ++++++++++++++++++++++++++++ net/mac80211/wext.c | 28 ---------------------------- 3 files changed, 29 insertions(+), 29 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 442a43a34005..199d64143b41 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -893,7 +893,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, /* wireless extensions */ extern const struct iw_handler_def ieee80211_iw_handler_def; -int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); /* STA/IBSS code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); @@ -1008,6 +1007,7 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt); void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); +int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/util.c b/net/mac80211/util.c index c3a22ab2ad2e..cf0b820a0eaa 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -612,3 +612,31 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, dev_queue_xmit(skb); } + +int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) +{ + int ret = -EINVAL; + struct ieee80211_channel *chan; + struct ieee80211_local *local = sdata->local; + + chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); + + if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { + if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + chan->flags & IEEE80211_CHAN_NO_IBSS) { + printk(KERN_DEBUG "%s: IBSS not allowed on frequency " + "%d MHz\n", sdata->dev->name, chan->center_freq); + return ret; + } + local->oper_channel = chan; + + if (local->sta_sw_scanning || local->sta_hw_scanning) + ret = 0; + else + ret = ieee80211_hw_config(local); + + rate_control_clear(local); + } + + return ret; +} diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index beae664ab480..97d132811c81 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -330,34 +330,6 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, return 0; } -int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) -{ - int ret = -EINVAL; - struct ieee80211_channel *chan; - struct ieee80211_local *local = sdata->local; - - chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); - - if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && - chan->flags & IEEE80211_CHAN_NO_IBSS) { - printk(KERN_DEBUG "%s: IBSS not allowed on frequency " - "%d MHz\n", sdata->dev->name, chan->center_freq); - return ret; - } - local->oper_channel = chan; - - if (local->sta_sw_scanning || local->sta_hw_scanning) - ret = 0; - else - ret = ieee80211_hw_config(local); - - rate_control_clear(local); - } - - return ret; -} - static int ieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) -- cgit v1.2.3 From 213cd118cbb88b76ae48f92cfb7dbef9a83cca62 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:54 +0200 Subject: mac80211: make bridge_packets a virtual interface option The bridge_packets configuration really should be per virtual interface (theoretically per AP/VLAN, but this is much easier); there currently is no way to set it yet though. Also invert the option to "NO_BRIDGE_PACKETS" so the default is to bridge. While at it, also document the flags properly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 4 ---- net/mac80211/ieee80211_i.h | 29 +++++++++++++++++++---------- net/mac80211/main.c | 2 -- net/mac80211/rx.c | 5 +++-- 4 files changed, 22 insertions(+), 18 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ee509f1109e2..24ce54463310 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -51,8 +51,6 @@ DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d", local->hw.conf.antenna_sel_tx); DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", local->hw.conf.antenna_sel_rx); -DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d", - local->bridge_packets); DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", local->rts_threshold); DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", @@ -206,7 +204,6 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(frequency); DEBUGFS_ADD(antenna_sel_tx); DEBUGFS_ADD(antenna_sel_rx); - DEBUGFS_ADD(bridge_packets); DEBUGFS_ADD(rts_threshold); DEBUGFS_ADD(fragmentation_threshold); DEBUGFS_ADD(short_retry_limit); @@ -263,7 +260,6 @@ void debugfs_hw_del(struct ieee80211_local *local) DEBUGFS_DEL(frequency); DEBUGFS_DEL(antenna_sel_tx); DEBUGFS_DEL(antenna_sel_rx); - DEBUGFS_DEL(bridge_packets); DEBUGFS_DEL(rts_threshold); DEBUGFS_DEL(fragmentation_threshold); DEBUGFS_DEL(short_retry_limit); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 199d64143b41..52f36ab1ee57 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -402,11 +402,25 @@ struct ieee80211_if_mesh { do { } while (0) #endif -/* flags used in struct ieee80211_sub_if_data.flags */ -#define IEEE80211_SDATA_ALLMULTI BIT(0) -#define IEEE80211_SDATA_PROMISC BIT(1) -#define IEEE80211_SDATA_USERSPACE_MLME BIT(2) -#define IEEE80211_SDATA_OPERATING_GMODE BIT(3) +/** + * enum ieee80211_sub_if_data_flags - virtual interface flags + * + * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets + * @IEEE80211_SDATA_PROMISC: interface is promisc + * @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active + * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode + * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between + * associated stations and deliver multicast frames both + * back to wireless media and to the local net stack. + */ +enum ieee80211_sub_if_data_flags { + IEEE80211_SDATA_ALLMULTI = BIT(0), + IEEE80211_SDATA_PROMISC = BIT(1), + IEEE80211_SDATA_USERSPACE_MLME = BIT(2), + IEEE80211_SDATA_OPERATING_GMODE = BIT(3), + IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4), +}; + struct ieee80211_sub_if_data { struct list_head list; @@ -635,10 +649,6 @@ struct ieee80211_local { struct crypto_blkcipher *wep_rx_tfm; u32 wep_iv; - int bridge_packets; /* bridge packets between associated stations and - * deliver multicast frames both back to wireless - * media and to the local net stack */ - struct list_head interfaces; /* @@ -726,7 +736,6 @@ struct ieee80211_local { struct dentry *frequency; struct dentry *antenna_sel_tx; struct dentry *antenna_sel_rx; - struct dentry *bridge_packets; struct dentry *rts_threshold; struct dentry *fragmentation_threshold; struct dentry *short_retry_limit; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 4bfac4b41c51..72e3f5574e9f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1280,8 +1280,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->hw.queues = 1; /* default */ - local->bridge_packets = 1; - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; local->short_retry_limit = 7; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 208563a27bc4..93f2cda9926e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1221,8 +1221,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) skb = rx->skb; xmit_skb = NULL; - if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP || - sdata->vif.type == IEEE80211_IF_TYPE_VLAN) && + if ((sdata->vif.type == IEEE80211_IF_TYPE_AP || + sdata->vif.type == IEEE80211_IF_TYPE_VLAN) && + !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && (rx->flags & IEEE80211_RX_RA_MATCH)) { if (is_multicast_ether_addr(ehdr->h_dest)) { /* -- cgit v1.2.3 From c2b13452b283f9c4a5b02a6b53ed6416ebf4c03c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:55 +0200 Subject: mac80211: clean up scan namespace Most of the scan functions are called ieee80211_sta_scan_* or similar, make clean it up so they are all just called ieee80211_scan_*. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 53 ++++++++-------- net/mac80211/main.c | 6 +- net/mac80211/mesh.c | 2 +- net/mac80211/mlme.c | 51 +++++++-------- net/mac80211/rx.c | 10 +-- net/mac80211/scan.c | 153 +++++++++++++++++++++++---------------------- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 2 +- net/mac80211/wext.c | 6 +- 9 files changed, 145 insertions(+), 140 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 52f36ab1ee57..5c38ea084540 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -71,9 +71,9 @@ struct ieee80211_fragment_entry { }; -struct ieee80211_sta_bss { +struct ieee80211_bss { struct list_head list; - struct ieee80211_sta_bss *hnext; + struct ieee80211_bss *hnext; size_t ssid_len; atomic_t users; @@ -112,7 +112,7 @@ struct ieee80211_sta_bss { u8 erp_value; }; -static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) +static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) { #ifdef CONFIG_MAC80211_MESH return bss->mesh_cfg; @@ -120,7 +120,7 @@ static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) return NULL; } -static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) +static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) { #ifdef CONFIG_MAC80211_MESH return bss->mesh_id; @@ -128,7 +128,7 @@ static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) return NULL; } -static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss) +static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) { #ifdef CONFIG_MAC80211_MESH return bss->mesh_id_len; @@ -658,8 +658,8 @@ struct ieee80211_local { spinlock_t key_lock; - bool sta_sw_scanning; - bool sta_hw_scanning; + /* Scanning and BSS list */ + bool sw_scanning, hw_scanning; int scan_channel_idx; enum ieee80211_band scan_band; @@ -670,9 +670,9 @@ struct ieee80211_local { struct ieee80211_channel *oper_channel, *scan_channel; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; - struct list_head sta_bss_list; - struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE]; - spinlock_t sta_bss_lock; + struct list_head bss_list; + struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; + spinlock_t bss_lock; /* SNMP counters */ /* dot11CountersTable */ @@ -905,7 +905,7 @@ extern const struct iw_handler_def ieee80211_iw_handler_def; /* STA/IBSS code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); -void ieee80211_sta_scan_work(struct work_struct *work); +void ieee80211_scan_work(struct work_struct *work); void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); @@ -926,35 +926,38 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); /* scan/BSS handling */ -int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); -int ieee80211_sta_scan_results(struct ieee80211_local *local, - struct iw_request_info *info, - char *buf, size_t len); -ieee80211_rx_result ieee80211_sta_rx_scan( - struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status); +int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + u8 *ssid, size_t ssid_len); +int ieee80211_scan_results(struct ieee80211_local *local, + struct iw_request_info *info, + char *buf, size_t len); +ieee80211_rx_result +ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_rx_status *rx_status); void ieee80211_rx_bss_list_init(struct ieee80211_local *local); void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); -int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, + char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); -int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, - u8 *ssid, size_t ssid_len); -struct ieee80211_sta_bss * +int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, + u8 *ssid, size_t ssid_len); +struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, struct ieee80211_mgmt *mgmt, size_t len, struct ieee802_11_elems *elems, int freq, bool beacon); -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss); + struct ieee80211_bss *bss); /* interface handling */ void ieee80211_if_setup(struct net_device *dev); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 72e3f5574e9f..4c424acc01a4 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -598,7 +598,7 @@ static int ieee80211_stop(struct net_device *dev) * the scan_sdata is NULL already don't send out a * scan event to userspace -- the scan is incomplete. */ - if (local->sta_sw_scanning) + if (local->sw_scanning) ieee80211_scan_completed(&local->hw); } @@ -732,7 +732,7 @@ int ieee80211_hw_config(struct ieee80211_local *local) struct ieee80211_channel *chan; int ret = 0; - if (local->sta_sw_scanning) + if (local->sw_scanning) chan = local->scan_channel; else chan = local->oper_channel; @@ -1290,7 +1290,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, spin_lock_init(&local->key_lock); - INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); + INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); sta_info_init(local); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a0141f5ff184..30cf891fd3a8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -566,7 +566,7 @@ static void ieee80211_mesh_work(struct work_struct *work) if (!netif_running(sdata->dev)) return; - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) return; while ((skb = skb_dequeue(&ifmsh->skb_queue))) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e14830106526..5b748447eb7d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -52,7 +52,7 @@ static int ecw2cw(int ecw) return (1 << ecw) - 1; } -static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) +static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) { u8 *end, *pos; @@ -72,7 +72,7 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) return NULL; } -static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, +static int ieee80211_compatible_rates(struct ieee80211_bss *bss, struct ieee80211_supported_band *sband, u64 *rates) { @@ -239,7 +239,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, u8 *pos, *ies, *ht_add_ie; int i, len, count, rates_len, supp_rates_len; u16 capab; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; u64 rates = 0; @@ -470,7 +470,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* MLME */ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; @@ -621,7 +621,7 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, } static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { u32 changed = 0; @@ -674,7 +674,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_conf *conf = &local_to_hw(local)->conf; u32 changed = BSS_CHANGED_ASSOC; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; ifsta->flags |= IEEE80211_STA_ASSOCIATED; @@ -846,7 +846,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int bss_privacy; int wep_privacy; int privacy_invoked; @@ -1219,7 +1219,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, /* Add STA entry for the AP */ sta = sta_info_get(local, ifsta->bssid); if (!sta) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int err; sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); @@ -1339,7 +1339,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { struct ieee80211_local *local = sdata->local; int res, rates, i, j; @@ -1490,7 +1490,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; int freq; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; struct sta_info *sta; struct ieee80211_channel *channel; u64 beacon_timestamp, rx_timestamp; @@ -1893,7 +1893,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->dev->name); - ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); + ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); } @@ -1974,7 +1974,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN], *pos; int i; @@ -2035,7 +2035,7 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int found = 0; u8 bssid[ETH_ALEN]; int active_ibss; @@ -2050,8 +2050,8 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", sdata->dev->name, active_ibss); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - spin_lock_bh(&local->sta_bss_lock); - list_for_each_entry(bss, &local->sta_bss_list, list) { + spin_lock_bh(&local->bss_lock); + list_for_each_entry(bss, &local->bss_list, list) { if (ifsta->ssid_len != bss->ssid_len || memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 || !(bss->capability & WLAN_CAPABILITY_IBSS)) @@ -2065,7 +2065,7 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) break; } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); #ifdef CONFIG_MAC80211_IBSS_DEBUG if (found) @@ -2110,7 +2110,7 @@ dont_join: IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->dev->name); - return ieee80211_sta_req_scan(sdata, ifsta->ssid, + return ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; @@ -2145,12 +2145,12 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss, *selected = NULL; + struct ieee80211_bss *bss, *selected = NULL; int top_rssi = 0, freq; - spin_lock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); freq = local->oper_channel->center_freq; - list_for_each_entry(bss, &local->sta_bss_list, list) { + list_for_each_entry(bss, &local->bss_list, list) { if (!(bss->capability & WLAN_CAPABILITY_ESS)) continue; @@ -2180,7 +2180,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, } if (selected) atomic_inc(&selected->users); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); if (selected) { ieee80211_set_freq(sdata, selected->freq); @@ -2207,9 +2207,9 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { ifsta->assoc_scan_tries++; if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(sdata, NULL, 0); + ieee80211_start_scan(sdata, NULL, 0); else - ieee80211_sta_start_scan(sdata, ifsta->ssid, + ieee80211_start_scan(sdata, ifsta->ssid, ifsta->ssid_len); ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); @@ -2231,7 +2231,7 @@ static void ieee80211_sta_work(struct work_struct *work) if (!netif_running(sdata->dev)) return; - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) return; if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && @@ -2246,7 +2246,8 @@ static void ieee80211_sta_work(struct work_struct *work) ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { - ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); + ieee80211_start_scan(sdata, ifsta->scan_ssid, + ifsta->scan_ssid_len); return; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 93f2cda9926e..582396a4fdb5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -403,12 +403,12 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) struct ieee80211_local *local = rx->local; struct sk_buff *skb = rx->skb; - if (unlikely(local->sta_hw_scanning)) - return ieee80211_sta_rx_scan(rx->sdata, skb, rx->status); + if (unlikely(local->hw_scanning)) + return ieee80211_scan_rx(rx->sdata, skb, rx->status); - if (unlikely(local->sta_sw_scanning)) { + if (unlikely(local->sw_scanning)) { /* drop all the other packets during a software scan anyway */ - if (ieee80211_sta_rx_scan(rx->sdata, skb, rx->status) + if (ieee80211_scan_rx(rx->sdata, skb, rx->status) != RX_QUEUED) dev_kfree_skb(skb); return RX_QUEUED; @@ -1918,7 +1918,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, return; } - if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning)) + if (unlikely(local->sw_scanning || local->hw_scanning)) rx.flags |= IEEE80211_RX_IN_SCAN; ieee80211_parse_qos(&rx); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 27727027d76d..5e719e7b720b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -32,26 +32,26 @@ void ieee80211_rx_bss_list_init(struct ieee80211_local *local) { - spin_lock_init(&local->sta_bss_lock); - INIT_LIST_HEAD(&local->sta_bss_list); + spin_lock_init(&local->bss_lock); + INIT_LIST_HEAD(&local->bss_list); } void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) { - struct ieee80211_sta_bss *bss, *tmp; + struct ieee80211_bss *bss, *tmp; - list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) + list_for_each_entry_safe(bss, tmp, &local->bss_list, list) ieee80211_rx_bss_put(local, bss); } -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[STA_HASH(bssid)]; + spin_lock_bh(&local->bss_lock); + bss = local->bss_hash[STA_HASH(bssid)]; while (bss) { if (!bss_mesh_cfg(bss) && !memcmp(bss->bssid, bssid, ETH_ALEN) && @@ -63,13 +63,13 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, } bss = bss->hnext; } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } -/* Caller must hold local->sta_bss_lock */ +/* Caller must hold local->bss_lock */ static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { u8 hash_idx; @@ -79,20 +79,20 @@ static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, else hash_idx = STA_HASH(bss->bssid); - bss->hnext = local->sta_bss_hash[hash_idx]; - local->sta_bss_hash[hash_idx] = bss; + bss->hnext = local->bss_hash[hash_idx]; + local->bss_hash[hash_idx] = bss; } -/* Caller must hold local->sta_bss_lock */ +/* Caller must hold local->bss_lock */ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { - struct ieee80211_sta_bss *b, *prev = NULL; - b = local->sta_bss_hash[STA_HASH(bss->bssid)]; + struct ieee80211_bss *b, *prev = NULL; + b = local->bss_hash[STA_HASH(bss->bssid)]; while (b) { if (b == bss) { if (!prev) - local->sta_bss_hash[STA_HASH(bss->bssid)] = + local->bss_hash[STA_HASH(bss->bssid)] = bss->hnext; else prev->hnext = bss->hnext; @@ -103,11 +103,11 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, } } -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); if (!bss) @@ -120,23 +120,23 @@ ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, bss->ssid_len = ssid_len; } - spin_lock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); + list_add_tail(&bss->list, &local->bss_list); __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } #ifdef CONFIG_MAC80211_MESH -static struct ieee80211_sta_bss * +static struct ieee80211_bss * ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int freq) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; + spin_lock_bh(&local->bss_lock); + bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; while (bss) { if (bss_mesh_cfg(bss) && !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && @@ -149,15 +149,15 @@ ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_i } bss = bss->hnext; } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } -static struct ieee80211_sta_bss * +static struct ieee80211_bss * ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int mesh_config_len, int freq) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; if (mesh_config_len != MESH_CFG_LEN) return NULL; @@ -186,16 +186,16 @@ ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_i memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); bss->mesh_id_len = mesh_id_len; bss->freq = freq; - spin_lock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); + list_add_tail(&bss->list, &local->bss_list); __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } #endif -static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) +static void ieee80211_rx_bss_free(struct ieee80211_bss *bss) { kfree(bss->ies); kfree(bss_mesh_id(bss)); @@ -204,21 +204,21 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) } void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { local_bh_disable(); - if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { + if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) { local_bh_enable(); return; } __ieee80211_rx_bss_hash_del(local, bss); list_del(&bss->list); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); ieee80211_rx_bss_free(bss); } -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, struct ieee80211_mgmt *mgmt, @@ -226,7 +226,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee802_11_elems *elems, int freq, bool beacon) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int clen; #ifdef CONFIG_MAC80211_MESH @@ -252,9 +252,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local, } else { #if 0 /* TODO: order by RSSI? */ - spin_lock_bh(&local->sta_bss_lock); - list_move_tail(&bss->list, &local->sta_bss_list); - spin_unlock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); + list_move_tail(&bss->list, &local->bss_list); + spin_unlock_bh(&local->bss_lock); #endif } @@ -327,11 +327,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local, } ieee80211_rx_result -ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status) +ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) { struct ieee80211_mgmt *mgmt; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; u8 *elements; struct ieee80211_channel *channel; size_t baselen; @@ -430,7 +430,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) struct ieee80211_sub_if_data *sdata; union iwreq_data wrqu; - if (WARN_ON(!local->sta_hw_scanning && !local->sta_sw_scanning)) + if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) return; local->last_scan_completed = jiffies; @@ -445,8 +445,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) if (sdata) wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); - if (local->sta_hw_scanning) { - local->sta_hw_scanning = 0; + if (local->hw_scanning) { + local->hw_scanning = false; if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " "channel after scan\n", wiphy_name(local->hw.wiphy)); @@ -454,7 +454,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) goto done; } - local->sta_sw_scanning = 0; + local->sw_scanning = false; if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " "channel after scan\n", wiphy_name(local->hw.wiphy)); @@ -492,7 +492,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) EXPORT_SYMBOL(ieee80211_scan_completed); -void ieee80211_sta_scan_work(struct work_struct *work) +void ieee80211_scan_work(struct work_struct *work) { struct ieee80211_local *local = container_of(work, struct ieee80211_local, scan_work.work); @@ -589,8 +589,8 @@ void ieee80211_sta_scan_work(struct work_struct *work) } -int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, - u8 *ssid, size_t ssid_len) +int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, + u8 *ssid, size_t ssid_len) { struct ieee80211_local *local = scan_sdata->local; struct ieee80211_sub_if_data *sdata; @@ -615,7 +615,7 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, * ResultCode: SUCCESS, INVALID_PARAMETERS */ - if (local->sta_sw_scanning || local->sta_hw_scanning) { + if (local->sw_scanning || local->hw_scanning) { if (local->scan_sdata == scan_sdata) return 0; return -EBUSY; @@ -624,17 +624,17 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, if (local->ops->hw_scan) { int rc; - local->sta_hw_scanning = 1; + local->hw_scanning = true; rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); if (rc) { - local->sta_hw_scanning = 0; + local->hw_scanning = false; return rc; } local->scan_sdata = scan_sdata; return 0; } - local->sta_sw_scanning = 1; + local->sw_scanning = true; rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { @@ -675,13 +675,14 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, } -int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) +int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + u8 *ssid, size_t ssid_len) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return ieee80211_sta_start_scan(sdata, ssid, ssid_len); + return ieee80211_start_scan(sdata, ssid, ssid_len); /* * STA has a state machine that might need to defer scanning @@ -689,7 +690,7 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t * queue it up to the state machine in that case. */ - if (local->sta_sw_scanning || local->sta_hw_scanning) { + if (local->sw_scanning || local->hw_scanning) { if (local->scan_sdata == sdata) return 0; return -EBUSY; @@ -707,9 +708,9 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t } -static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, - struct ieee80211_sta_bss *bss, - char **current_ev, char *end_buf) +static void ieee80211_scan_add_ies(struct iw_request_info *info, + struct ieee80211_bss *bss, + char **current_ev, char *end_buf) { u8 *pos, *end, *next; struct iw_event iwe; @@ -749,10 +750,10 @@ static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, static char * -ieee80211_sta_scan_result(struct ieee80211_local *local, - struct iw_request_info *info, - struct ieee80211_sta_bss *bss, - char *current_ev, char *end_buf) +ieee80211_scan_result(struct ieee80211_local *local, + struct iw_request_info *info, + struct ieee80211_bss *bss, + char *current_ev, char *end_buf) { struct iw_event iwe; char *buf; @@ -828,7 +829,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); - ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); + ieee80211_scan_add_ies(info, bss, ¤t_ev, end_buf); if (bss->supp_rates_len > 0) { /* display all supported rates in readable format */ @@ -914,23 +915,23 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, } -int ieee80211_sta_scan_results(struct ieee80211_local *local, - struct iw_request_info *info, - char *buf, size_t len) +int ieee80211_scan_results(struct ieee80211_local *local, + struct iw_request_info *info, + char *buf, size_t len) { char *current_ev = buf; char *end_buf = buf + len; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; - spin_lock_bh(&local->sta_bss_lock); - list_for_each_entry(bss, &local->sta_bss_list, list) { + spin_lock_bh(&local->bss_lock); + list_for_each_entry(bss, &local->bss_list, list) { if (buf + len - current_ev <= IW_EV_ADDR_LEN) { - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return -E2BIG; } - current_ev = ieee80211_sta_scan_result(local, info, bss, + current_ev = ieee80211_scan_result(local, info, bss, current_ev, end_buf); } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return current_ev - buf; } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1059b17c83b0..e606ba08ddd4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -222,7 +222,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) return TX_CONTINUE; - if (unlikely(tx->local->sta_sw_scanning) && + if (unlikely(tx->local->sw_scanning) && !ieee80211_is_probe_req(hdr->frame_control)) return TX_DROP; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cf0b820a0eaa..a7968df9dacb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -630,7 +630,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) } local->oper_channel = chan; - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) ret = 0; else ret = ieee80211_hw_config(local); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 97d132811c81..77b68ed8b832 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -552,7 +552,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, ssid_len = req->essid_len; } - return ieee80211_sta_req_scan(sdata, ssid, ssid_len); + return ieee80211_request_scan(sdata, ssid, ssid_len); } @@ -566,10 +566,10 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) return -EAGAIN; - res = ieee80211_sta_scan_results(local, info, extra, data->length); + res = ieee80211_scan_results(local, info, extra, data->length); if (res >= 0) { data->length = res; return 0; -- cgit v1.2.3 From ccd7b36286f8c42b3fa95c5a8d402162ffab41df Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:56 +0200 Subject: mac80211: clean up some comments Some comments refer to 80211.o or similar; also remove a comment about implementing fragments better, we really have better things to do. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 7 ++----- net/mac80211/rx.c | 4 ++-- net/mac80211/tx.c | 15 +-------------- net/mac80211/wme.h | 1 - 4 files changed, 5 insertions(+), 22 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5c38ea084540..1f9336a30e3b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -29,9 +29,6 @@ #include "key.h" #include "sta_info.h" -/* ieee80211.o internal definitions, etc. These are not included into - * low-level drivers. */ - struct ieee80211_local; /* Maximum number of broadcast/multicast frames to buffer when some of the @@ -293,13 +290,13 @@ struct mesh_config { #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) -/* flags for MLME request*/ +/* flags for MLME request */ #define IEEE80211_STA_REQ_SCAN 0 #define IEEE80211_STA_REQ_DIRECT_PROBE 1 #define IEEE80211_STA_REQ_AUTH 2 #define IEEE80211_STA_REQ_RUN 3 -/* flags used for setting mlme state */ +/* STA/IBSS MLME states */ enum ieee80211_sta_mlme_state { IEEE80211_STA_MLME_DISABLED, IEEE80211_STA_MLME_DIRECT_PROBE, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 582396a4fdb5..33530b29c422 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -501,8 +501,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) /* Drop disallowed frame classes based on STA auth/assoc state; * IEEE 802.11, Chap 5.5. * - * 80211.o does filtering only based on association state, i.e., it - * drops Class 3 frames from not associated stations. hostapd sends + * mac80211 filters only based on association state, i.e. it drops + * Class 3 frames from not associated stations. hostapd sends * deauth/disassoc frames when needed. In addition, hostapd is * responsible for filtering on both auth and assoc states. */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e606ba08ddd4..1bed3be01c26 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -111,7 +111,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, hdr = (struct ieee80211_hdr *)tx->skb->data; if (ieee80211_is_ctl(hdr->frame_control)) { /* TODO: These control frames are not currently sent by - * 80211.o, but should they be implemented, this function + * mac80211, but should they be implemented, this function * needs to be updated to support duration field calculation. * * RTS: time needed to transmit pending data/mgmt frame plus @@ -1580,19 +1580,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, nh_pos -= skip_header_bytes; h_pos -= skip_header_bytes; - /* TODO: implement support for fragments so that there is no need to - * reallocate and copy payload; it might be enough to support one - * extra fragment that would be copied in the beginning of the frame - * data.. anyway, it would be nice to include this into skb structure - * somehow - * - * There are few options for this: - * use skb->cb as an extra space for 802.11 header - * allocate new buffer if not enough headroom - * make sure that there is enough headroom in every skb by increasing - * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and - * alloc_skb() (net/core/skbuff.c) - */ head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); /* diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 465e274df7c5..bc62f28a4d3d 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h @@ -1,5 +1,4 @@ /* - * IEEE 802.11 driver (80211.o) - QoS datatypes * Copyright 2004, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * -- cgit v1.2.3 From 96dd22ac06b0dbfb069fdf530c72046a941e9694 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:57 +0200 Subject: mac80211: inform driver of basic rateset Drivers need to know the basic rateset to be able to configure the ACK/CTS programming in hardware correctly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ++++++ net/mac80211/ieee80211_i.h | 7 ++----- net/mac80211/iface.c | 4 +++- net/mac80211/mlme.c | 40 +++++++++------------------------------- net/mac80211/tx.c | 4 ++-- net/mac80211/util.c | 28 ++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 39 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d67882dd3604..c81e579c17f3 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -160,6 +160,7 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_ERP_PREAMBLE: preamble changed * @BSS_CHANGED_ERP_SLOT: slot timing changed * @BSS_CHANGED_HT: 802.11n parameters changed + * @BSS_CHANGED_BASIC_RATES: Basic rateset changed */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -167,6 +168,7 @@ enum ieee80211_bss_change { BSS_CHANGED_ERP_PREAMBLE = 1<<2, BSS_CHANGED_ERP_SLOT = 1<<3, BSS_CHANGED_HT = 1<<4, + BSS_CHANGED_BASIC_RATES = 1<<5, }; /** @@ -187,6 +189,9 @@ enum ieee80211_bss_change { * @assoc_ht: association in HT mode * @ht_conf: ht capabilities * @ht_bss_conf: ht extended capabilities + * @basic_rates: bitmap of basic rates, each bit stands for an + * index into the rate table configured by the driver in + * the current band. */ struct ieee80211_bss_conf { /* association related data */ @@ -200,6 +205,7 @@ struct ieee80211_bss_conf { u16 beacon_int; u16 assoc_capability; u64 timestamp; + u64 basic_rates; /* ht related data */ bool assoc_ht; struct ieee80211_ht_info *ht_conf; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1f9336a30e3b..21cc6d07b020 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -433,11 +433,6 @@ struct ieee80211_sub_if_data { int drop_unencrypted; - /* - * basic rates of this AP or the AP we're associated to - */ - u64 basic_rates; - /* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; unsigned int fragment_next; @@ -1017,6 +1012,8 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, void ieee802_11_parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems); int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); +u64 ieee80211_mandatory_rates(struct ieee80211_local *local, + enum ieee80211_band band); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 61b19340488c..dab8eba2602f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -144,7 +144,9 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, ieee80211_setup_sdata(sdata, type); /* reset some values that shouldn't be kept across type changes */ - sdata->basic_rates = 0; + sdata->bss_conf.basic_rates = + ieee80211_mandatory_rates(sdata->local, + sdata->local->hw.conf.channel->band); sdata->drop_unencrypted = 0; return 0; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5b748447eb7d..55bc60713937 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -710,6 +710,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_led_assoc(local, 1); sdata->bss_conf.assoc = 1; + /* + * For now just always ask the driver to update the basic rateset + * when we have associated, we aren't checking whether it actually + * changed or not. + */ + changed |= BSS_CHANGED_BASIC_RATES; ieee80211_bss_info_change_notify(sdata, changed); netif_tx_start_all_queues(sdata->dev); @@ -1296,7 +1302,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, } sta->supp_rates[local->hw.conf.channel->band] = rates; - sdata->basic_rates = basic_rates; + sdata->bss_conf.basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && @@ -1453,34 +1459,6 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, return res; } -static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, - enum ieee80211_band band) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_rate *bitrates; - u64 mandatory_rates; - enum ieee80211_rate_flags mandatory_flag; - int i; - - sband = local->hw.wiphy->bands[band]; - if (!sband) { - WARN_ON(1); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - } - - if (band == IEEE80211_BAND_2GHZ) - mandatory_flag = IEEE80211_RATE_MANDATORY_B; - else - mandatory_flag = IEEE80211_RATE_MANDATORY_A; - - bitrates = sband->bitrates; - mandatory_rates = 0; - for (i = 0; i < sband->n_bitrates; i++) - if (bitrates[i].flags & mandatory_flag) - mandatory_rates |= BIT(i); - return mandatory_rates; -} - static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, @@ -1522,7 +1500,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, prev_rates = sta->supp_rates[band]; /* make sure mandatory rates are always added */ sta->supp_rates[band] = supp_rates | - ieee80211_sta_get_mandatory_rates(local, band); + ieee80211_mandatory_rates(local, band); #ifdef CONFIG_MAC80211_IBSS_DEBUG if (sta->supp_rates[band] != prev_rates) @@ -2361,7 +2339,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, /* make sure mandatory rates are always added */ sta->supp_rates[band] = supp_rates | - ieee80211_sta_get_mandatory_rates(local, band); + ieee80211_mandatory_rates(local, band); rate_control_rate_init(sta, local); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1bed3be01c26..a523189f10c4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -153,7 +153,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, if (r->bitrate > txrate->bitrate) break; - if (tx->sdata->basic_rates & BIT(i)) + if (tx->sdata->bss_conf.basic_rates & BIT(i)) rate = r->bitrate; switch (sband->band) { @@ -594,7 +594,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) for (idx = 0; idx < sband->n_bitrates; idx++) { if (sband->bitrates[idx].bitrate > rate->bitrate) continue; - if (tx->sdata->basic_rates & BIT(idx) && + if (tx->sdata->bss_conf.basic_rates & BIT(idx) && (baserate < 0 || (sband->bitrates[baserate].bitrate < sband->bitrates[idx].bitrate))) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a7968df9dacb..d6aca91e612d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -640,3 +640,31 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) return ret; } + +u64 ieee80211_mandatory_rates(struct ieee80211_local *local, + enum ieee80211_band band) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_rate *bitrates; + u64 mandatory_rates; + enum ieee80211_rate_flags mandatory_flag; + int i; + + sband = local->hw.wiphy->bands[band]; + if (!sband) { + WARN_ON(1); + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + } + + if (band == IEEE80211_BAND_2GHZ) + mandatory_flag = IEEE80211_RATE_MANDATORY_B; + else + mandatory_flag = IEEE80211_RATE_MANDATORY_A; + + bitrates = sband->bitrates; + mandatory_rates = 0; + for (i = 0; i < sband->n_bitrates; i++) + if (bitrates[i].flags & mandatory_flag) + mandatory_rates |= BIT(i); + return mandatory_rates; +} -- cgit v1.2.3 From 05c914fe330fa8e1cc67870dc0d3809dfd96c107 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:58 +0200 Subject: mac80211: use nl80211 interface types There's really no reason for mac80211 to be using its own interface type defines. Use the nl80211 types and simplify the configuration code a bit: there's no need to translate them any more now. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 22 +++---- drivers/net/wireless/ath5k/ath5k.h | 4 +- drivers/net/wireless/ath5k/attach.c | 2 +- drivers/net/wireless/ath5k/base.c | 50 ++++++++-------- drivers/net/wireless/ath5k/base.h | 2 +- drivers/net/wireless/ath5k/pcu.c | 12 ++-- drivers/net/wireless/ath5k/reset.c | 2 +- drivers/net/wireless/ath9k/main.c | 28 ++++----- drivers/net/wireless/b43/main.c | 38 ++++++------ drivers/net/wireless/b43/phy_common.c | 4 +- drivers/net/wireless/b43legacy/main.c | 30 +++++----- drivers/net/wireless/b43legacy/phy.c | 4 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 6 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 64 ++++++++++----------- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-scan.c | 4 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 20 +++---- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 84 +++++++++++++-------------- drivers/net/wireless/libertas_tf/main.c | 18 +++--- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/p54/p54common.c | 14 ++--- drivers/net/wireless/p54/p54pci.c | 4 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00config.c | 8 +-- drivers/net/wireless/rt2x00/rt2x00dev.c | 8 +-- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 18 +++--- drivers/net/wireless/rtl8180_dev.c | 10 ++-- drivers/net/wireless/rtl8187_dev.c | 8 +-- drivers/net/wireless/zd1211rw/zd_mac.c | 20 +++---- include/net/mac80211.h | 35 ++---------- net/mac80211/cfg.c | 57 ++++++++---------- net/mac80211/debugfs_netdev.c | 28 ++++----- net/mac80211/ht.c | 6 +- net/mac80211/ieee80211_i.h | 6 +- net/mac80211/iface.c | 40 +++++++------ net/mac80211/key.c | 6 +- net/mac80211/main.c | 89 ++++++++++++++--------------- net/mac80211/mlme.c | 40 ++++++------- net/mac80211/rx.c | 65 ++++++++++----------- net/mac80211/scan.c | 8 +-- net/mac80211/sta_info.c | 4 +- net/mac80211/tx.c | 28 ++++----- net/mac80211/util.c | 44 +++++++------- net/mac80211/wext.c | 84 +++++++++++++-------------- 53 files changed, 517 insertions(+), 551 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index c6a55cd12db9..b2c050b68890 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -765,11 +765,11 @@ static void adm8211_update_mode(struct ieee80211_hw *dev) priv->soft_rx_crc = 0; switch (priv->mode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->nar &= ~(ADM8211_NAR_PR | ADM8211_NAR_EA); priv->nar |= ADM8211_NAR_ST | ADM8211_NAR_SR; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: priv->nar &= ~ADM8211_NAR_PR; priv->nar |= ADM8211_NAR_EA | ADM8211_NAR_ST | ADM8211_NAR_SR; @@ -777,7 +777,7 @@ static void adm8211_update_mode(struct ieee80211_hw *dev) if (priv->pdev->revision >= ADM8211_REV_BA) priv->soft_rx_crc = 1; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: priv->nar &= ~(ADM8211_NAR_EA | ADM8211_NAR_ST); priv->nar |= ADM8211_NAR_PR | ADM8211_NAR_SR; break; @@ -1410,11 +1410,11 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf) { struct adm8211_priv *priv = dev->priv; - if (priv->mode != IEEE80211_IF_TYPE_MNTR) + if (priv->mode != NL80211_IFTYPE_MONITOR) return -EOPNOTSUPP; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->mode = conf->type; break; default: @@ -1437,7 +1437,7 @@ static void adm8211_remove_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf) { struct adm8211_priv *priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; } static int adm8211_init_rings(struct ieee80211_hw *dev) @@ -1556,7 +1556,7 @@ static int adm8211_start(struct ieee80211_hw *dev) ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE | ADM8211_IER_RCIE | ADM8211_IER_TCIE | ADM8211_IER_TDUIE | ADM8211_IER_GPTIE); - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; adm8211_update_mode(dev); ADM8211_CSR_WRITE(RDR, 0); @@ -1571,7 +1571,7 @@ static void adm8211_stop(struct ieee80211_hw *dev) { struct adm8211_priv *priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_INVALID; + priv->mode = NL80211_IFTYPE_UNSPECIFIED; priv->nar = 0; ADM8211_CSR_WRITE(NAR, 0); ADM8211_CSR_WRITE(IER, 0); @@ -1896,7 +1896,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, priv->tx_power = 0x40; priv->lpf_cutoff = 0xFF; priv->lnags_threshold = 0xFF; - priv->mode = IEEE80211_IF_TYPE_INVALID; + priv->mode = NL80211_IFTYPE_UNSPECIFIED; /* Power-on issue. EEPROM won't read correctly without */ if (pdev->revision >= ADM8211_REV_BA) { @@ -1986,7 +1986,7 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) struct ieee80211_hw *dev = pci_get_drvdata(pdev); struct adm8211_priv *priv = dev->priv; - if (priv->mode != IEEE80211_IF_TYPE_INVALID) { + if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) { ieee80211_stop_queues(dev); adm8211_stop(dev); } @@ -2004,7 +2004,7 @@ static int adm8211_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - if (priv->mode != IEEE80211_IF_TYPE_INVALID) { + if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) { adm8211_start(dev); ieee80211_wake_queues(dev); } diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 4c0211798a7a..20018869051d 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -1008,7 +1008,7 @@ struct ath5k_hw { enum ath5k_int ah_imr; - enum ieee80211_if_types ah_op_mode; + enum nl80211_iftype ah_op_mode; enum ath5k_power_mode ah_power_mode; struct ieee80211_channel ah_current_channel; bool ah_turbo; @@ -1117,7 +1117,7 @@ extern void ath5k_hw_detach(struct ath5k_hw *ah); /* Reset Functions */ extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); -extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel); +extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); /* Power management functions */ extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index 0eb2511fe147..153c4111fabe 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c @@ -124,7 +124,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* * HW information */ - ah->ah_op_mode = IEEE80211_IF_TYPE_STA; + ah->ah_op_mode = NL80211_IFTYPE_STATION; ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; ah->ah_turbo = false; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 85260c39aa2b..e09ed2ce6753 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -507,7 +507,7 @@ ath5k_pci_probe(struct pci_dev *pdev, sc->iobase = mem; /* So we can unmap it on detach */ sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ - sc->opmode = IEEE80211_IF_TYPE_STA; + sc->opmode = NL80211_IFTYPE_STATION; mutex_init(&sc->lock); spin_lock_init(&sc->rxbuflock); spin_lock_init(&sc->txbuflock); @@ -1377,8 +1377,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc) ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); if (ret) return ret; - if (sc->opmode == IEEE80211_IF_TYPE_AP || - sc->opmode == IEEE80211_IF_TYPE_MESH_POINT) { + if (sc->opmode == NL80211_IFTYPE_AP || + sc->opmode == NL80211_IFTYPE_MESH_POINT) { /* * Always burst out beacon and CAB traffic * (aifs = cwmin = cwmax = 0) @@ -1386,7 +1386,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc) qi.tqi_aifs = 0; qi.tqi_cw_min = 0; qi.tqi_cw_max = 0; - } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { + } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { /* * Adhoc mode; backoff between 0 and (2 * cw_min). */ @@ -1714,7 +1714,7 @@ ath5k_tasklet_rx(unsigned long data) /* let crypto-error packets fall through in MNTR */ if ((rs.rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || - sc->opmode != IEEE80211_IF_TYPE_MNTR) + sc->opmode != NL80211_IFTYPE_MONITOR) goto next; } accept: @@ -1777,7 +1777,7 @@ accept: ath5k_debug_dump_skb(sc, skb, "RX ", 0); /* check beacons in IBSS mode */ - if (sc->opmode == IEEE80211_IF_TYPE_IBSS) + if (sc->opmode == NL80211_IFTYPE_ADHOC) ath5k_check_ibss_tsf(sc, skb, &rxs); __ieee80211_rx(sc->hw, skb, &rxs); @@ -1892,7 +1892,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ds = bf->desc; flags = AR5K_TXDESC_NOACK; - if (sc->opmode == IEEE80211_IF_TYPE_IBSS && ath5k_hw_hasveol(ah)) { + if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { ds->ds_link = bf->daddr; /* self-linked */ flags |= AR5K_TXDESC_VEOL; /* @@ -1941,8 +1941,8 @@ ath5k_beacon_send(struct ath5k_softc *sc) ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); - if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA || - sc->opmode == IEEE80211_IF_TYPE_MNTR)) { + if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || + sc->opmode == NL80211_IFTYPE_MONITOR)) { ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); return; } @@ -2116,9 +2116,9 @@ ath5k_beacon_config(struct ath5k_softc *sc) sc->bmisscount = 0; sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); - if (sc->opmode == IEEE80211_IF_TYPE_STA) { + if (sc->opmode == NL80211_IFTYPE_STATION) { sc->imask |= AR5K_INT_BMISS; - } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { + } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { /* * In IBSS mode we use a self-linked tx descriptor and let the * hardware send the beacons automatically. We have to load it @@ -2323,7 +2323,7 @@ ath5k_intr(int irq, void *dev_id) * transmission time) in order to detect wether * automatic TSF updates happened. */ - if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { + if (sc->opmode == NL80211_IFTYPE_ADHOC) { /* XXX: only if VEOL suppported */ u64 tsf = ath5k_hw_get_tsf64(ah); sc->nexttbtt += sc->bintval; @@ -2553,7 +2553,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ath5k_debug_dump_skb(sc, skb, "TX ", 1); - if (sc->opmode == IEEE80211_IF_TYPE_MNTR) + if (sc->opmode == NL80211_IFTYPE_MONITOR) ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); /* @@ -2688,9 +2688,9 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, sc->vif = conf->vif; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MONITOR: sc->opmode = conf->type; break; default: @@ -2761,7 +2761,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (conf->changed & IEEE80211_IFCC_BEACON && - vif->type == IEEE80211_IF_TYPE_IBSS) { + vif->type == NL80211_IFTYPE_ADHOC) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); if (!beacon) { ret = -ENOMEM; @@ -2880,17 +2880,17 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ - if (sc->opmode == IEEE80211_IF_TYPE_MNTR) + if (sc->opmode == NL80211_IFTYPE_MONITOR) rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM; - if (sc->opmode != IEEE80211_IF_TYPE_STA) + if (sc->opmode != NL80211_IFTYPE_STATION) rfilt |= AR5K_RX_FILTER_PROBEREQ; - if (sc->opmode != IEEE80211_IF_TYPE_AP && - sc->opmode != IEEE80211_IF_TYPE_MESH_POINT && + if (sc->opmode != NL80211_IFTYPE_AP && + sc->opmode != NL80211_IFTYPE_MESH_POINT && test_bit(ATH_STAT_PROMISC, sc->status)) rfilt |= AR5K_RX_FILTER_PROM; - if (sc->opmode == IEEE80211_IF_TYPE_STA || - sc->opmode == IEEE80211_IF_TYPE_IBSS) { + if (sc->opmode == NL80211_IFTYPE_STATION || + sc->opmode == NL80211_IFTYPE_ADHOC) { rfilt |= AR5K_RX_FILTER_BEACON; } @@ -2995,7 +2995,7 @@ ath5k_reset_tsf(struct ieee80211_hw *hw) * in IBSS mode we need to update the beacon timers too. * this will also reset the TSF if we call it with 0 */ - if (sc->opmode == IEEE80211_IF_TYPE_IBSS) + if (sc->opmode == NL80211_IFTYPE_ADHOC) ath5k_beacon_update_timers(sc, 0); else ath5k_hw_reset_tsf(sc->ah); @@ -3010,7 +3010,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ath5k_debug_dump_skb(sc, skb, "BC ", 1); - if (sc->opmode != IEEE80211_IF_TYPE_IBSS) { + if (sc->opmode != NL80211_IFTYPE_ADHOC) { ret = -EIO; goto end; } diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index 1549b63d6138..9d0b728928e3 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -113,7 +113,7 @@ struct ath5k_softc { struct ieee80211_channel channels[ATH_CHAN_MAX]; struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; u8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - enum ieee80211_if_types opmode; + enum nl80211_iftype opmode; struct ath5k_hw *ah; /* Atheros HW */ struct ieee80211_supported_band *curband; diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 5a896d1e2a2b..c77cee2a5582 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -52,26 +52,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) ATH5K_TRACE(ah->ah_sc); switch (ah->ah_op_mode) { - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA | (ah->ah_version == AR5K_AR5210 ? AR5K_STA_ID1_NO_PSPOLL : 0); beacon_reg |= AR5K_BCR_ADHOC; break; - case IEEE80211_IF_TYPE_AP: - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA | (ah->ah_version == AR5K_AR5210 ? AR5K_STA_ID1_NO_PSPOLL : 0); beacon_reg |= AR5K_BCR_AP; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | (ah->ah_version == AR5K_AR5210 ? AR5K_STA_ID1_PWR_SV : 0); - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA | (ah->ah_version == AR5K_AR5210 ? AR5K_STA_ID1_NO_PSPOLL : 0); @@ -649,7 +649,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) * Set the additional timers by mode */ switch (ah->ah_op_mode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: if (ah->ah_version == AR5K_AR5210) { timer1 = 0xffffffff; timer2 = 0xffffffff; diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index d260fba0180f..f5c3de890cdb 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -399,7 +399,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) /* * Main reset function */ -int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, +int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index b493dff5643e..2a6e089062f3 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -140,7 +140,7 @@ static int ath_key_config(struct ath_softc *sc, struct ath9k_keyval hk; const u8 *mac = NULL; int ret = 0; - enum ieee80211_if_types opmode; + enum nl80211_iftype opmode; memset(&hk, 0, sizeof(hk)); @@ -179,14 +179,14 @@ static int ath_key_config(struct ath_softc *sc, */ if (is_broadcast_ether_addr(addr)) { switch (opmode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: /* default key: could be group WPA key * or could be static WEP key */ mac = NULL; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: break; - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: break; default: ASSERT(0); @@ -1147,13 +1147,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, return -ENOBUFS; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: ic_opmode = ATH9K_M_STA; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: ic_opmode = ATH9K_M_IBSS; break; - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: ic_opmode = ATH9K_M_HOSTAP; break; default: @@ -1275,7 +1275,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, /* TODO: Need to decide which hw opmode to use for multi-interface * cases */ - if (vif->type == IEEE80211_IF_TYPE_AP && + if (vif->type == NL80211_IFTYPE_AP && ah->ah_opmode != ATH9K_M_HOSTAP) { ah->ah_opmode = ATH9K_M_HOSTAP; ath9k_hw_setopmode(ah); @@ -1287,8 +1287,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, if ((conf->changed & IEEE80211_IFCC_BSSID) && !is_zero_ether_addr(conf->bssid)) { switch (vif->type) { - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: /* Update ratectrl about the new state */ ath_rate_newstate(sc, avp); @@ -1333,8 +1333,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } if ((conf->changed & IEEE80211_IFCC_BEACON) && - ((vif->type == IEEE80211_IF_TYPE_IBSS) || - (vif->type == IEEE80211_IF_TYPE_AP))) { + ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP))) { /* * Allocate and setup the beacon frame. * @@ -1353,7 +1353,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } /* Check for WLAN_CAPABILITY_PRIVACY ? */ - if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) { + if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { for (i = 0; i < IEEE80211_WEP_NKID; i++) if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) ath9k_hw_keysetmac(sc->sc_ah, @@ -1362,7 +1362,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } /* Only legacy IBSS for now */ - if (vif->type == IEEE80211_IF_TYPE_IBSS) + if (vif->type == NL80211_IFTYPE_ADHOC) ath_update_chainmask(sc, 0); return 0; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d4a356b11636..df7a1e7f4a52 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1244,13 +1244,13 @@ generate_new: static void handle_irq_tbtt_indication(struct b43_wldev *dev) { - if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) { + if (b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) { ///TODO: PS TBTT } else { if (1 /*FIXME: the last PSpoll frame was sent successfully */ ) b43_power_saving_ctl_bits(dev, 0); } - if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) + if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) dev->dfq_valid = 1; } @@ -1599,8 +1599,8 @@ static void handle_irq_beacon(struct b43_wldev *dev) struct b43_wl *wl = dev->wl; u32 cmd, beacon0_valid, beacon1_valid; - if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP) && - !b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) + if (!b43_is_mode(wl, NL80211_IFTYPE_AP) && + !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) return; /* This is the bottom half of the asynchronous beacon update. */ @@ -2568,10 +2568,10 @@ static void b43_adjust_opmode(struct b43_wldev *dev) ctl &= ~B43_MACCTL_BEACPROMISC; ctl |= B43_MACCTL_INFRA; - if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || - b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) + if (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) ctl |= B43_MACCTL_AP; - else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) + else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) ctl &= ~B43_MACCTL_INFRA; if (wl->filter_flags & FIF_CONTROL) @@ -3406,8 +3406,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) phy->ops->set_rx_antenna(dev, antenna); /* Update templates for AP/mesh mode. */ - if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || - b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) + if (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) b43_set_beacon_int(dev, conf->beacon_int); if (!!conf->radio_enabled != phy->radio_on) { @@ -3595,14 +3595,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, else memset(wl->bssid, 0, ETH_ALEN); if (b43_status(dev) >= B43_STAT_INITIALIZED) { - if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || - b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { + if (b43_is_mode(wl, NL80211_IFTYPE_AP) || + b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { B43_WARN_ON(vif->type != wl->if_type); if (conf->changed & IEEE80211_IFCC_SSID) b43_set_ssid(dev, conf->ssid, conf->ssid_len); if (conf->changed & IEEE80211_IFCC_BEACON) b43_update_templates(wl); - } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) { + } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { if (conf->changed & IEEE80211_IFCC_BEACON) b43_update_templates(wl); } @@ -3903,7 +3903,7 @@ static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) pu_delay = 3700; else pu_delay = 1050; - if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) + if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle) pu_delay = 500; if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) pu_delay = max(pu_delay, (u16)2400); @@ -3917,7 +3917,7 @@ static void b43_set_pretbtt(struct b43_wldev *dev) u16 pretbtt; /* The time value is in microseconds. */ - if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) { + if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) { pretbtt = 2; } else { if (dev->phy.type == B43_PHYTYPE_A) @@ -4084,11 +4084,11 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ - if (conf->type != IEEE80211_IF_TYPE_AP && - conf->type != IEEE80211_IF_TYPE_MESH_POINT && - conf->type != IEEE80211_IF_TYPE_STA && - conf->type != IEEE80211_IF_TYPE_WDS && - conf->type != IEEE80211_IF_TYPE_IBSS) + if (conf->type != NL80211_IFTYPE_AP && + conf->type != NL80211_IFTYPE_MESH_POINT && + conf->type != NL80211_IFTYPE_STATION && + conf->type != NL80211_IFTYPE_WDS && + conf->type != NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; mutex_lock(&wl->mutex); diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 4d4345d76abf..af37abccccb3 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -162,7 +162,7 @@ void b43_phy_lock(struct b43_wldev *dev) #endif B43_WARN_ON(dev->dev->id.revision < 3); - if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) + if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); } @@ -174,7 +174,7 @@ void b43_phy_unlock(struct b43_wldev *dev) #endif B43_WARN_ON(dev->dev->id.revision < 3); - if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) + if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43_power_saving_ctl_bits(dev, 0); } diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 68f63f5093af..6e425410c99d 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -888,13 +888,13 @@ generate_new: static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev) { - if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) { + if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) { /* TODO: PS TBTT */ } else { if (1/*FIXME: the last PSpoll frame was sent successfully */) b43legacy_power_saving_ctl_bits(dev, -1, -1); } - if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) + if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) dev->dfq_valid = 1; } @@ -1201,7 +1201,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev) struct b43legacy_wl *wl = dev->wl; u32 cmd; - if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) + if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) return; /* This is the bottom half of the asynchronous beacon update. */ @@ -1936,9 +1936,9 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev) ctl &= ~B43legacy_MACCTL_BEACPROMISC; ctl |= B43legacy_MACCTL_INFRA; - if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) + if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) ctl |= B43legacy_MACCTL_AP; - else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) + else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) ctl &= ~B43legacy_MACCTL_INFRA; if (wl->filter_flags & FIF_CONTROL) @@ -2646,7 +2646,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, b43legacy_mgmtframe_txantenna(dev, antenna_tx); /* Update templates for AP mode. */ - if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) + if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) b43legacy_set_beacon_int(dev, conf->beacon_int); @@ -2733,12 +2733,12 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw, else memset(wl->bssid, 0, ETH_ALEN); if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { - if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) { - B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP); + if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) { + B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP); b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len); if (conf->changed & IEEE80211_IFCC_BEACON) b43legacy_update_templates(wl); - } else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) { + } else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) { if (conf->changed & IEEE80211_IFCC_BEACON) b43legacy_update_templates(wl); } @@ -3020,7 +3020,7 @@ static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, bool idle) { u16 pu_delay = 1050; - if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) + if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle) pu_delay = 500; if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) pu_delay = max(pu_delay, (u16)2400); @@ -3035,7 +3035,7 @@ static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) u16 pretbtt; /* The time value is in microseconds. */ - if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) + if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) pretbtt = 2; else pretbtt = 250; @@ -3259,10 +3259,10 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ - if (conf->type != IEEE80211_IF_TYPE_AP && - conf->type != IEEE80211_IF_TYPE_STA && - conf->type != IEEE80211_IF_TYPE_WDS && - conf->type != IEEE80211_IF_TYPE_IBSS) + if (conf->type != NL80211_IFTYPE_AP && + conf->type != NL80211_IFTYPE_STATION && + conf->type != NL80211_IFTYPE_WDS && + conf->type != NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; mutex_lock(&wl->mutex); diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index bed67a54250c..4c9442b16f3f 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -103,7 +103,7 @@ void b43legacy_phy_lock(struct b43legacy_wldev *dev) if (dev->dev->id.revision < 3) { b43legacy_mac_suspend(dev); } else { - if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) + if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43legacy_power_saving_ctl_bits(dev, -1, 1); } } @@ -118,7 +118,7 @@ void b43legacy_phy_unlock(struct b43legacy_wldev *dev) if (dev->dev->id.revision < 3) { b43legacy_mac_enable(dev); } else { - if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) + if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43legacy_power_saving_ctl_bits(dev, -1, -1); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 10c64bdb314c..da23c927380f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -682,7 +682,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, rs_sta = (void *)sta->rate_ctrl_priv; - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !rs_sta->ibss_sta_added) { u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 3d100e898249..7ca5627cc078 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -520,10 +520,10 @@ static int iwl3945_is_network_packet(struct iwl3945_priv *priv, /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ + case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr3, priv->bssid); - case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ + case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr2, priv->bssid); default: @@ -807,7 +807,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, priv->stations[sta_id].current_rate.rate_n_flags = rate; - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && (sta_id != priv->hw_setting.bcast_sta_id) && (sta_id != IWL_MULTICAST_ID)) priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 9bbbc9d7c0e8..2a4933b5fb64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -851,7 +851,7 @@ struct iwl3945_priv { /* eeprom */ struct iwl3945_eeprom eeprom; - enum ieee80211_if_types iw_mode; + enum nl80211_iftype iw_mode; struct sk_buff *ibss_beacon; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index c293e5b6cbb5..700da67ac288 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -821,7 +821,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) goto out; @@ -2093,7 +2093,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, i = sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) + (priv->iw_mode == NL80211_IFTYPE_ADHOC)) goto out; valid_tx_ant = priv->hw_params.valid_tx_ant; @@ -2163,7 +2163,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; i = sta->last_txrate_idx; - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) { u8 sta_id = iwl_find_station(priv, hdr->addr1); DECLARE_MAC_BUF(mac); @@ -2243,7 +2243,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ lq_sta->ibss_sta_added = 0; - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { u8 sta_id = iwl_find_station(priv, sta->addr); DECLARE_MAC_BUF(mac); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 31ea28858896..e8db33bf5e5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -337,7 +337,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ if (new_assoc) { - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { ret = iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1); if (ret == IWL_INVALID_STATION) { @@ -448,8 +448,8 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, const u8 *dest, int left) { if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && - (priv->iw_mode != IEEE80211_IF_TYPE_AP))) + ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && + (priv->iw_mode != NL80211_IFTYPE_AP))) return 0; if (priv->ibss_beacon->len > left) @@ -672,7 +672,7 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv) beacon_int = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { if (beacon_int == 0) { priv->rxon_timing.beacon_interval = cpu_to_le16(100); priv->rxon_timing.beacon_init_val = cpu_to_le32(102400); @@ -721,7 +721,7 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv, else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; @@ -740,23 +740,23 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; @@ -785,7 +785,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) * in some case A channels are all non IBSS * in this case force B/G channel */ - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info))) ch_info = &priv->channel_info[0]; @@ -1182,7 +1182,7 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, le32_to_cpu(beacon->low_tsf), rate); #endif - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!test_bit(STATUS_EXIT_PENDING, &priv->status))) queue_work(priv->workqueue, &priv->beacon_update); } @@ -2388,7 +2388,7 @@ static void iwl4965_bg_set_monitor(struct work_struct *work) mutex_lock(&priv->mutex); - ret = iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR); + ret = iwl4965_set_mode(priv, NL80211_IFTYPE_MONITOR); if (ret) { if (ret == -EAGAIN) @@ -2469,7 +2469,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) DECLARE_MAC_BUF(mac); unsigned long flags; - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { IWL_ERROR("%s Should not be called in AP mode\n", __func__); return; } @@ -2524,7 +2524,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -2532,10 +2532,10 @@ static void iwl4965_post_associate(struct iwl_priv *priv) iwl4965_commit_rxon(priv); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: /* assume default assoc id */ priv->assoc_id = 1; @@ -2551,7 +2551,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) break; } - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->assoc_station_added = 1; spin_lock_irqsave(&priv->lock, flags); @@ -2828,7 +2828,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && !is_channel_ibss(ch_info)) { IWL_ERROR("channel %d in band %d not IBSS channel\n", conf->channel->hw_value, conf->channel->band); @@ -2943,7 +2943,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -2982,7 +2982,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return 0; } - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && conf->changed & IEEE80211_IFCC_BEACON) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); if (!beacon) @@ -2992,7 +2992,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return rc; } - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); @@ -3015,7 +3015,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { if (!conf->bssid) { conf->bssid = priv->mac_addr; memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); @@ -3050,11 +3050,11 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, * to verify) - jpk */ memcpy(priv->bssid, conf->bssid, ETH_ALEN); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl4965_config_ap(priv); else { rc = iwl4965_commit_rxon(priv); - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl_rxon_add_station( priv, priv->active_rxon.bssid_addr, 1); } @@ -3090,7 +3090,7 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw, if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", - IEEE80211_IF_TYPE_MNTR, + NL80211_IFTYPE_MONITOR, changed_flags, *total_flags); /* queue work 'cuz mac80211 is holding a lock which * prevents us from issuing (synchronous) f/w cmds */ @@ -3204,7 +3204,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len) goto out_unlock; } - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */ + if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */ ret = -EIO; IWL_ERROR("ERROR: APs don't scan\n"); goto out_unlock; @@ -3329,7 +3329,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * in 1X mode. * In legacy wep mode, we use another host command to the uCode */ if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && - priv->iw_mode != IEEE80211_IF_TYPE_AP) { + priv->iw_mode != NL80211_IFTYPE_AP) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; else @@ -3400,7 +3400,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl_activate_qos(priv, 1); else if (priv->assoc_id && iwl_is_associated(priv)) iwl_activate_qos(priv, 0); @@ -3518,7 +3518,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) priv->beacon_int = priv->hw->conf.beacon_int; priv->timestamp = 0; - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA)) + if ((priv->iw_mode == NL80211_IFTYPE_STATION)) priv->beacon_int = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -3532,7 +3532,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); @@ -3541,7 +3541,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) iwl_power_update_mode(priv, 0); /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { /* switch to CAM during association period. * the ucode will block any association/authentication @@ -3580,7 +3580,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk return -EIO; } - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { IWL_DEBUG_MAC80211("leave - not IBSS\n"); mutex_unlock(&priv->mutex); return -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 36d08b0eec43..d80184ee911c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -306,14 +306,14 @@ void iwl_reset_qos(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); priv->qos_data.qos_active = 0; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; if (!(priv->active_rate & 0xfff0)) { cw_min = 31; is_legacy = 1; } - } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + } else if (priv->iw_mode == NL80211_IFTYPE_AP) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { @@ -932,7 +932,7 @@ int iwl_init_drv(struct iwl_priv *priv) priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; - priv->iw_mode = IEEE80211_IF_TYPE_STA; + priv->iw_mode = NL80211_IFTYPE_STATION; priv->use_ant_b_for_management_frame = 1; /* start with ant B */ priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; @@ -1396,7 +1396,7 @@ void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv) iwl_scan_cancel(priv); /* FIXME: This is a workaround for AP */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { spin_lock_irqsave(&priv->lock, flags); iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1823687e5820..c018121085e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -954,7 +954,7 @@ struct iwl_priv { u8 *eeprom; struct iwl_eeprom_calib_info *calib_info; - enum ieee80211_if_types iw_mode; + enum nl80211_iftype iw_mode; struct sk_buff *ibss_beacon; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 55ec31ec9e15..60a03d2d2d0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -290,7 +290,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) final_mode = setting->critical_power_setting; /* driver only support CAM for non STA network */ - if (priv->iw_mode != IEEE80211_IF_TYPE_STA) + if (priv->iw_mode != NL80211_IFTYPE_STATION) final_mode = IWL_POWER_MODE_CAM; if (!iwl_is_rfkill(priv) && !setting->power_disabled && diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index faad4d3f56e1..38b2946b1d81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1026,10 +1026,10 @@ static int iwl_is_network_packet(struct iwl_priv *priv, /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ + case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr3, priv->bssid); - case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ + case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ /* packets to our IBSS update information */ return !compare_ether_addr(header->addr2, priv->bssid); default: @@ -1169,7 +1169,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, rx_status.flag |= RX_FLAG_SHORTPRE; /* Take shortcut when only in monitor mode */ - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { iwl_pass_packet_to_mac80211(priv, include_phy, rxb, &rx_status); return; @@ -1186,7 +1186,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, switch (fc & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_MGMT: case IEEE80211_FTYPE_DATA: - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, header->addr2); /* fall through */ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index d026aaf62335..09c264be0496 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -463,7 +463,7 @@ void iwl_init_scan_params(struct iwl_priv *priv) int iwl_scan_initiate(struct iwl_priv *priv) { - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { IWL_ERROR("APs don't scan.\n"); return 0; } @@ -868,7 +868,7 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index a72569f1acb5..61797f3f8d5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -47,8 +47,8 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) unsigned long flags; DECLARE_MAC_BUF(mac); - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) || - (priv->iw_mode == IEEE80211_IF_TYPE_AP)) + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || + (priv->iw_mode == NL80211_IFTYPE_AP)) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) @@ -74,7 +74,7 @@ EXPORT_SYMBOL(iwl_find_station); int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { return IWL_AP_ID; } else { u8 *da = ieee80211_get_DA(hdr); @@ -286,7 +286,7 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, /* BCAST station and IBSS stations do not work in HT mode */ if (sta_id != priv->hw_params.bcast_sta_id && - priv->iw_mode != IEEE80211_IF_TYPE_IBSS) + priv->iw_mode != NL80211_IFTYPE_ADHOC) iwl_set_ht_add_station(priv, sta_id, ht_info); spin_unlock_irqrestore(&priv->sta_lock, flags_spin); @@ -817,7 +817,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, }; if ((lq->sta_id == 0xFF) && - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) + (priv->iw_mode == NL80211_IFTYPE_ADHOC)) return -EINVAL; if (lq->sta_id == 0xFF) @@ -904,7 +904,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) if ((is_ap) && (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && - (priv->iw_mode == IEEE80211_IF_TYPE_STA)) + (priv->iw_mode == NL80211_IFTYPE_STATION)) sta_id = iwl_add_station_flags(priv, addr, is_ap, 0, cur_ht_config); else @@ -938,11 +938,11 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If we are a client station in a BSS network, use the special * AP station entry (that's the only station we communicate with) */ - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: return IWL_AP_ID; /* If we are an AP, then find the station, or use BCAST */ - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: sta_id = iwl_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -950,7 +950,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: sta_id = iwl_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -970,7 +970,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) /* If we are in monitor mode, use BCAST. This is required for * packet injection. */ - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: return priv->hw_params.bcast_sta_id; default: diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 9d5bcf46cbe9..e9feca4033f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -814,10 +814,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != IEEE80211_IF_TYPE_MNTR || + (priv->iw_mode != NL80211_IFTYPE_MONITOR || !(info->flags & IEEE80211_TX_CTL_INJECTED)) && /* packet injection */ (!iwl_is_associated(priv) || - ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || + ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || !priv->assoc_station_added)) { IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); goto drop_unlock; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index cbbe73a12887..e6c6ef6ad62e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1160,7 +1160,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ if (iwl3945_is_associated(priv) && - (priv->iw_mode == IEEE80211_IF_TYPE_STA)) + (priv->iw_mode == NL80211_IFTYPE_STATION)) if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0) == IWL_INVALID_STATION) { IWL_ERROR("Error adding AP address for transmit.\n"); @@ -1447,8 +1447,8 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, { if (!iwl3945_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && - (priv->iw_mode != IEEE80211_IF_TYPE_AP))) + ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && + (priv->iw_mode != NL80211_IFTYPE_AP))) return 0; if (priv->ibss_beacon->len > left) @@ -1746,14 +1746,14 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv) spin_lock_irqsave(&priv->lock, flags); priv->qos_data.qos_active = 0; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; if (!(priv->active_rate & 0xfff0)) { cw_min = 31; is_legacy = 1; } - } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + } else if (priv->iw_mode == NL80211_IFTYPE_AP) { if (priv->qos_data.qos_enable) priv->qos_data.qos_active = 1; } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { @@ -2120,7 +2120,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) beacon_int = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { + if (priv->iw_mode == NL80211_IFTYPE_STATION) { if (beacon_int == 0) { priv->rxon_timing.beacon_interval = cpu_to_le16(100); priv->rxon_timing.beacon_init_val = cpu_to_le32(102400); @@ -2156,7 +2156,7 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv) static int iwl3945_scan_initiate(struct iwl3945_priv *priv) { - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { IWL_ERROR("APs don't scan.\n"); return 0; } @@ -2218,7 +2218,7 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; @@ -2237,23 +2237,23 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: priv->staging_rxon.dev_type = RXON_DEV_TYPE_SNIFFER; priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; @@ -2282,7 +2282,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) * in some case A channels are all non IBSS * in this case force B/G channel */ - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info))) ch_info = &priv->channel_info[0]; @@ -2302,7 +2302,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) { - if (mode == IEEE80211_IF_TYPE_IBSS) { + if (mode == NL80211_IFTYPE_ADHOC) { const struct iwl3945_channel_info *ch_info; ch_info = iwl3945_get_channel_info(priv, @@ -2469,11 +2469,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h /* If we are a client station in a BSS network, use the special * AP station entry (that's the only station we communicate with) */ - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: return IWL_AP_ID; /* If we are an AP, then find the station, or use BCAST */ - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: sta_id = iwl3945_hw_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; @@ -2481,7 +2481,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ - case IEEE80211_IF_TYPE_IBSS: { + case NL80211_IFTYPE_ADHOC: { DECLARE_MAC_BUF(mac); /* Create new station table entry */ @@ -2502,7 +2502,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h } /* If we are in monitor mode, use BCAST. This is required for * packet injection. */ - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: return priv->hw_setting.bcast_sta_id; default: @@ -2565,9 +2565,9 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) /* drop all data frame if we are not associated */ if (ieee80211_is_data(fc) && - (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */ + (priv->iw_mode != NL80211_IFTYPE_MONITOR) && /* packet injection */ (!iwl3945_is_associated(priv) || - ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) { + ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; } @@ -2806,7 +2806,7 @@ static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio) if (disable_radio) { iwl3945_scan_cancel(priv); /* FIXME: This is a workaround for AP */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { spin_lock_irqsave(&priv->lock, flags); iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); @@ -3161,7 +3161,7 @@ static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv, le32_to_cpu(beacon->low_tsf), rate); #endif - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!test_bit(STATUS_EXIT_PENDING, &priv->status))) queue_work(priv->workqueue, &priv->beacon_update); } @@ -6059,7 +6059,7 @@ static void iwl3945_bg_set_monitor(struct work_struct *work) if (!iwl3945_is_ready(priv)) IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); else - if (iwl3945_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0) + if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0) IWL_ERROR("iwl3945_set_mode() failed\n"); mutex_unlock(&priv->mutex); @@ -6248,7 +6248,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* select Rx antennas */ scan->flags |= iwl3945_get_antenna_flags(priv); - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->channel_count = @@ -6323,7 +6323,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) struct ieee80211_conf *conf = NULL; DECLARE_MAC_BUF(mac); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { IWL_ERROR("%s Should not be called in AP mode\n", __func__); return; } @@ -6372,7 +6372,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) else priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -6380,11 +6380,11 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) iwl3945_commit_rxon(priv); switch (priv->iw_mode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: /* clear out the station table */ iwl3945_clear_stations_table(priv); @@ -6754,7 +6754,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } @@ -6791,7 +6791,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, } /* handle this temporarily here */ - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && + if (priv->iw_mode == NL80211_IFTYPE_ADHOC && conf->changed & IEEE80211_IFCC_BEACON) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); if (!beacon) @@ -6803,7 +6803,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, /* XXX: this MUST use conf->mac_addr */ - if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && + if ((priv->iw_mode == NL80211_IFTYPE_AP) && (!conf->ssid_len)) { IWL_DEBUG_MAC80211 ("Leaving in AP mode because HostAPD is not ready.\n"); @@ -6826,7 +6826,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode == NL80211_IFTYPE_AP) { if (!conf->bssid) { conf->bssid = priv->mac_addr; memcpy(priv->bssid, priv->mac_addr, ETH_ALEN); @@ -6861,11 +6861,11 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, * to verify) - jpk */ memcpy(priv->bssid, conf->bssid, ETH_ALEN); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl3945_config_ap(priv); else { rc = iwl3945_commit_rxon(priv); - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc) + if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0); } @@ -6901,7 +6901,7 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", - IEEE80211_IF_TYPE_MNTR, + NL80211_IFTYPE_MONITOR, changed_flags, *total_flags); /* queue work 'cuz mac80211 is holding a lock which * prevents us from issuing (synchronous) f/w cmds */ @@ -7010,7 +7010,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) goto out_unlock; } - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { /* APs don't scan */ + if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */ rc = -EIO; IWL_ERROR("ERROR: APs don't scan\n"); goto out_unlock; @@ -7152,7 +7152,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) + if (priv->iw_mode == NL80211_IFTYPE_AP) iwl3945_activate_qos(priv, 1); else if (priv->assoc_id && iwl3945_is_associated(priv)) iwl3945_activate_qos(priv, 0); @@ -7239,7 +7239,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) priv->beacon_int = priv->hw->conf.beacon_int; priv->timestamp1 = 0; priv->timestamp0 = 0; - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA)) + if ((priv->iw_mode == NL80211_IFTYPE_STATION)) priv->beacon_int = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -7253,14 +7253,14 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ - if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (priv->iw_mode != NL80211_IFTYPE_AP) { iwl3945_scan_cancel_timeout(priv, 100); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwl3945_commit_rxon(priv); } /* Per mac80211.h: This is only used in IBSS mode... */ - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { IWL_DEBUG_MAC80211("leave - not in IBSS\n"); mutex_unlock(&priv->mutex); @@ -7289,7 +7289,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk return -EIO; } - if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { IWL_DEBUG_MAC80211("leave - not IBSS\n"); mutex_unlock(&priv->mutex); return -EIO; @@ -7996,7 +7996,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("Radio disabled.\n"); } - priv->iw_mode = IEEE80211_IF_TYPE_STA; + priv->iw_mode = NL80211_IFTYPE_STATION; printk(KERN_INFO DRV_NAME ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index c948021bff6a..feff945ad856 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -219,7 +219,7 @@ static void lbtf_tx_work(struct work_struct *work) struct sk_buff *skb = NULL; int err; - if ((priv->vif->type == IEEE80211_IF_TYPE_AP) && + if ((priv->vif->type == NL80211_IFTYPE_AP) && (!skb_queue_empty(&priv->bc_ps_buf))) skb = skb_dequeue(&priv->bc_ps_buf); else if (priv->skb_to_tx) { @@ -326,11 +326,11 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, priv->vif = conf->vif; switch (conf->type) { - case IEEE80211_IF_TYPE_MESH_POINT: - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: lbtf_set_mode(priv, LBTF_AP_MODE); break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: lbtf_set_mode(priv, LBTF_STA_MODE); break; default: @@ -346,8 +346,8 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw, { struct lbtf_private *priv = hw->priv; - if (priv->vif->type == IEEE80211_IF_TYPE_AP || - priv->vif->type == IEEE80211_IF_TYPE_MESH_POINT) + if (priv->vif->type == NL80211_IFTYPE_AP || + priv->vif->type == NL80211_IFTYPE_MESH_POINT) lbtf_beacon_ctrl(priv, 0, 0); lbtf_set_mode(priv, LBTF_PASSIVE_MODE); lbtf_set_bssid(priv, 0, NULL); @@ -372,8 +372,8 @@ static int lbtf_op_config_interface(struct ieee80211_hw *hw, struct sk_buff *beacon; switch (priv->vif->type) { - case IEEE80211_IF_TYPE_AP: - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: beacon = ieee80211_beacon_get(hw, vif); if (beacon) { lbtf_beacon_set(priv, beacon); @@ -614,7 +614,7 @@ void lbtf_bcn_sent(struct lbtf_private *priv) { struct sk_buff *skb = NULL; - if (priv->vif->type != IEEE80211_IF_TYPE_AP) + if (priv->vif->type != NL80211_IFTYPE_AP) return; if (skb_queue_empty(&priv->bc_ps_buf)) { diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 6ba50f087f7b..e855211a90f8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -267,7 +267,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, struct sk_buff *skb; struct ieee80211_tx_info *info; - if (vif->type != IEEE80211_IF_TYPE_AP) + if (vif->type != NL80211_IFTYPE_AP) return; skb = ieee80211_beacon_get(hw, vif); diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index da51786254dc..bac58ed03e5c 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1139,7 +1139,7 @@ static int p54_start(struct ieee80211_hw *dev) err = priv->open(dev); if (!err) - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; p54_init_vdcf(dev); @@ -1157,7 +1157,7 @@ static void p54_stop(struct ieee80211_hw *dev) kfree_skb(skb); priv->stop(dev); priv->tsf_high32 = priv->tsf_low32 = 0; - priv->mode = IEEE80211_IF_TYPE_INVALID; + priv->mode = NL80211_IFTYPE_UNSPECIFIED; } static int p54_add_interface(struct ieee80211_hw *dev, @@ -1165,11 +1165,11 @@ static int p54_add_interface(struct ieee80211_hw *dev, { struct p54_common *priv = dev->priv; - if (priv->mode != IEEE80211_IF_TYPE_MNTR) + if (priv->mode != NL80211_IFTYPE_MONITOR) return -EOPNOTSUPP; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->mode = conf->type; break; default: @@ -1181,7 +1181,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, p54_set_filter(dev, 0, NULL); switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: p54_set_filter(dev, 1, NULL); break; default: @@ -1198,7 +1198,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf) { struct p54_common *priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; memset(priv->mac_addr, 0, ETH_ALEN); p54_set_filter(dev, 0, NULL); } @@ -1380,7 +1380,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) return NULL; priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_INVALID; + priv->mode = NL80211_IFTYPE_UNSPECIFIED; skb_queue_head_init(&priv->tx_queue); dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ IEEE80211_HW_RX_INCLUDES_FCS | diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 1594786205f8..1c2a02a741af 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -616,7 +616,7 @@ static int p54p_suspend(struct pci_dev *pdev, pm_message_t state) struct ieee80211_hw *dev = pci_get_drvdata(pdev); struct p54p_priv *priv = dev->priv; - if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) { + if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) { ieee80211_stop_queues(dev); p54p_stop(dev); } @@ -634,7 +634,7 @@ static int p54p_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) { + if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) { p54p_open(dev); ieee80211_wake_queues(dev); } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index cb5f2d01a9c3..d3bf7bba611a 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -384,7 +384,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, - 2 * (conf->type != IEEE80211_IF_TYPE_STA)); + 2 * (conf->type != NL80211_IFTYPE_STATION)); rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6f296cef76ad..1359a3768404 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -483,7 +483,7 @@ struct rt2x00intf_conf { /* * Interface type */ - enum ieee80211_if_types type; + enum nl80211_iftype type; /* * TSF sync value, this is dependant on the operation type. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index ca051f50ef10..4d5e87b015a0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -31,7 +31,7 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, - enum ieee80211_if_types type, + enum nl80211_iftype type, u8 *mac, u8 *bssid) { struct rt2x00intf_conf conf; @@ -40,11 +40,11 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, conf.type = type; switch (type) { - case IEEE80211_IF_TYPE_IBSS: - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: conf.sync = TSF_SYNC_BEACON; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: conf.sync = TSF_SYNC_INFRA; break; default: diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2f3bfc606880..86840e3585e8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -467,8 +467,8 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac, struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); - if (vif->type != IEEE80211_IF_TYPE_AP && - vif->type != IEEE80211_IF_TYPE_IBSS) + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_ADHOC) return; /* @@ -1212,8 +1212,8 @@ static void rt2x00lib_resume_intf(void *data, u8 *mac, /* * Master or Ad-hoc mode require a new beacon update. */ - if (vif->type == IEEE80211_IF_TYPE_AP || - vif->type == IEEE80211_IF_TYPE_IBSS) + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC) intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 7bbc16b1b6c6..797eb619aa0a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -88,7 +88,7 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); */ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, - enum ieee80211_if_types type, + enum nl80211_iftype type, u8 *mac, u8 *bssid); void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 56829fad3471..485c40de5cc0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -211,7 +211,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, return -ENODEV; switch (conf->type) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: /* * We don't support mixed combinations of * sta and ap interfaces. @@ -227,8 +227,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, return -ENOBUFS; break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: /* * We don't support mixed combinations of * sta and ap interfaces. @@ -268,7 +268,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * increase interface count and start initialization. */ - if (conf->type == IEEE80211_IF_TYPE_AP) + if (conf->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count++; else rt2x00dev->intf_sta_count++; @@ -277,7 +277,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, spin_lock_init(&intf->seqlock); intf->beacon = entry; - if (conf->type == IEEE80211_IF_TYPE_AP) + if (conf->type == NL80211_IFTYPE_AP) memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); @@ -311,11 +311,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * no interface is present. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) || - (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count)) + (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || + (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) return; - if (conf->type == IEEE80211_IF_TYPE_AP) + if (conf->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count--; else rt2x00dev->intf_sta_count--; @@ -331,7 +331,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * are cleared to prevent false ACKing of frames. */ rt2x00lib_config_intf(rt2x00dev, intf, - IEEE80211_IF_TYPE_INVALID, NULL, NULL); + NL80211_IFTYPE_UNSPECIFIED, NULL, NULL); } EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 861c76a65d6a..abcd641c54be 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -615,7 +615,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) reg |= RTL818X_CMD_TX_ENABLE; rtl818x_iowrite8(priv, &priv->map->CMD, reg); - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; return 0; err_free_rings: @@ -633,7 +633,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev) u8 reg; int i; - priv->mode = IEEE80211_IF_TYPE_INVALID; + priv->mode = NL80211_IFTYPE_UNSPECIFIED; rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); @@ -661,11 +661,11 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, { struct rtl8180_priv *priv = dev->priv; - if (priv->mode != IEEE80211_IF_TYPE_MNTR) + if (priv->mode != NL80211_IFTYPE_MONITOR) return -EOPNOTSUPP; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->mode = conf->type; break; default: @@ -688,7 +688,7 @@ static void rtl8180_remove_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf) { struct rtl8180_priv *priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; priv->vif = NULL; } diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 8a42bfa6d4f0..e9902613e2ee 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -836,11 +836,11 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, struct rtl8187_priv *priv = dev->priv; int i; - if (priv->mode != IEEE80211_IF_TYPE_MNTR) + if (priv->mode != NL80211_IFTYPE_MONITOR) return -EOPNOTSUPP; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: priv->mode = conf->type; break; default: @@ -865,7 +865,7 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev, { struct rtl8187_priv *priv = dev->priv; mutex_lock(&priv->conf_mutex); - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; priv->vif = NULL; mutex_unlock(&priv->conf_mutex); } @@ -1057,7 +1057,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - priv->mode = IEEE80211_IF_TYPE_MNTR; + priv->mode = NL80211_IFTYPE_MONITOR; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 3005dd1fde42..a3da014f928d 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -716,15 +716,15 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, { struct zd_mac *mac = zd_hw_mac(hw); - /* using IEEE80211_IF_TYPE_INVALID to indicate no mode selected */ - if (mac->type != IEEE80211_IF_TYPE_INVALID) + /* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */ + if (mac->type != NL80211_IFTYPE_UNSPECIFIED) return -EOPNOTSUPP; switch (conf->type) { - case IEEE80211_IF_TYPE_MNTR: - case IEEE80211_IF_TYPE_MESH_POINT: - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: mac->type = conf->type; break; default: @@ -738,7 +738,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct zd_mac *mac = zd_hw_mac(hw); - mac->type = IEEE80211_IF_TYPE_INVALID; + mac->type = NL80211_IFTYPE_UNSPECIFIED; zd_set_beacon_interval(&mac->chip, 0); zd_write_mac_addr(&mac->chip, NULL); } @@ -757,8 +757,8 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, int associated; int r; - if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || - mac->type == IEEE80211_IF_TYPE_IBSS) { + if (mac->type == NL80211_IFTYPE_MESH_POINT || + mac->type == NL80211_IFTYPE_ADHOC) { associated = true; if (conf->changed & IEEE80211_IFCC_BEACON) { struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); @@ -955,7 +955,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) spin_lock_init(&mac->lock); mac->hw = hw; - mac->type = IEEE80211_IF_TYPE_INVALID; + mac->type = NL80211_IFTYPE_UNSPECIFIED; memcpy(mac->channels, zd_channels, sizeof(zd_channels)); memcpy(mac->rates, zd_rates, sizeof(zd_rates)); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index c81e579c17f3..7f5ea55e00f5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -477,33 +477,6 @@ struct ieee80211_conf { struct ieee80211_ht_bss_info ht_bss_conf; }; -/** - * enum ieee80211_if_types - types of 802.11 network interfaces - * - * @IEEE80211_IF_TYPE_INVALID: invalid interface type, not used - * by mac80211 itself - * @IEEE80211_IF_TYPE_AP: interface in AP mode. - * @IEEE80211_IF_TYPE_MGMT: special interface for communication with hostap - * daemon. Drivers should never see this type. - * @IEEE80211_IF_TYPE_STA: interface in STA (client) mode. - * @IEEE80211_IF_TYPE_IBSS: interface in IBSS (ad-hoc) mode. - * @IEEE80211_IF_TYPE_MNTR: interface in monitor (rfmon) mode. - * @IEEE80211_IF_TYPE_WDS: interface in WDS mode. - * @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers - * will never see this type. - * @IEEE80211_IF_TYPE_MESH_POINT: 802.11s mesh point - */ -enum ieee80211_if_types { - IEEE80211_IF_TYPE_INVALID, - IEEE80211_IF_TYPE_AP, - IEEE80211_IF_TYPE_STA, - IEEE80211_IF_TYPE_IBSS, - IEEE80211_IF_TYPE_MESH_POINT, - IEEE80211_IF_TYPE_MNTR, - IEEE80211_IF_TYPE_WDS, - IEEE80211_IF_TYPE_VLAN, -}; - /** * struct ieee80211_vif - per-interface data * @@ -515,7 +488,7 @@ enum ieee80211_if_types { * sizeof(void *). */ struct ieee80211_vif { - enum ieee80211_if_types type; + enum nl80211_iftype type; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); }; @@ -523,7 +496,7 @@ struct ieee80211_vif { static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) { #ifdef CONFIG_MAC80211_MESH - return vif->type == IEEE80211_IF_TYPE_MESH_POINT; + return vif->type == NL80211_IFTYPE_MESH_POINT; #endif return false; } @@ -534,7 +507,7 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) * @vif: pointer to a driver-use per-interface structure. The pointer * itself is also used for various functions including * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). - * @type: one of &enum ieee80211_if_types constants. Determines the type of + * @type: one of &enum nl80211_iftype constants. Determines the type of * added/removed interface. * @mac_addr: pointer to MAC address of the interface. This pointer is valid * until the interface is removed (i.e. it cannot be used after @@ -550,7 +523,7 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) * in pure monitor mode. */ struct ieee80211_if_init_conf { - enum ieee80211_if_types type; + enum nl80211_iftype type; struct ieee80211_vif *vif; void *mac_addr; }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6ec2127f9a60..d004351050cc 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -24,26 +24,19 @@ struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy) } EXPORT_SYMBOL(wiphy_to_hw); -static enum ieee80211_if_types -nl80211_type_to_mac80211_type(enum nl80211_iftype type) +static bool nl80211_type_check(enum nl80211_iftype type) { switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - return IEEE80211_IF_TYPE_STA; case NL80211_IFTYPE_ADHOC: - return IEEE80211_IF_TYPE_IBSS; case NL80211_IFTYPE_STATION: - return IEEE80211_IF_TYPE_STA; case NL80211_IFTYPE_MONITOR: - return IEEE80211_IF_TYPE_MNTR; #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: - return IEEE80211_IF_TYPE_MESH_POINT; #endif case NL80211_IFTYPE_WDS: - return IEEE80211_IF_TYPE_WDS; + return true; default: - return IEEE80211_IF_TYPE_INVALID; + return false; } } @@ -52,17 +45,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, struct vif_params *params) { struct ieee80211_local *local = wiphy_priv(wiphy); - enum ieee80211_if_types itype; struct net_device *dev; struct ieee80211_sub_if_data *sdata; int err; - itype = nl80211_type_to_mac80211_type(type); - if (itype == IEEE80211_IF_TYPE_INVALID) + if (!nl80211_type_check(type)) return -EINVAL; - err = ieee80211_if_add(local, name, &dev, itype, params); - if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) + err = ieee80211_if_add(local, name, &dev, type, params); + if (err || type != NL80211_IFTYPE_MONITOR || !flags) return err; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -93,7 +84,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, { struct ieee80211_local *local = wiphy_priv(wiphy); struct net_device *dev; - enum ieee80211_if_types itype; struct ieee80211_sub_if_data *sdata; int ret; @@ -102,8 +92,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, if (!dev) return -ENODEV; - itype = nl80211_type_to_mac80211_type(type); - if (itype == IEEE80211_IF_TYPE_INVALID) + if (!nl80211_type_check(type)) return -EINVAL; if (dev == local->mdev) @@ -111,7 +100,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ret = ieee80211_if_change_type(sdata, itype); + ret = ieee80211_if_change_type(sdata, type); if (ret) return ret; @@ -120,7 +109,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, params->mesh_id_len, params->mesh_id); - if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) + if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) return 0; sdata->u.mntr_flags = *flags; @@ -516,7 +505,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; old = sdata->u.ap.beacon; @@ -539,7 +528,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; old = sdata->u.ap.beacon; @@ -561,7 +550,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; old = sdata->u.ap.beacon; @@ -716,8 +705,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, if (params->vlan) { sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); - if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN && - sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && + sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; } else sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -747,8 +736,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, return err; } - if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN || - sdata->vif.type == IEEE80211_IF_TYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || + sdata->vif.type == NL80211_IFTYPE_AP) ieee80211_send_layer2_update(sta); rcu_read_unlock(); @@ -812,8 +801,8 @@ static int ieee80211_change_station(struct wiphy *wiphy, if (params->vlan && params->vlan != sta->sdata->dev) { vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); - if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN && - vlansdata->vif.type != IEEE80211_IF_TYPE_AP) { + if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && + vlansdata->vif.type != NL80211_IFTYPE_AP) { rcu_read_unlock(); return -EINVAL; } @@ -847,7 +836,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) return -ENOTSUPP; rcu_read_lock(); @@ -903,7 +892,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) return -ENOTSUPP; rcu_read_lock(); @@ -978,7 +967,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) return -ENOTSUPP; rcu_read_lock(); @@ -1006,7 +995,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) return -ENOTSUPP; rcu_read_lock(); @@ -1035,7 +1024,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; if (params->use_cts_prot >= 0) { diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 0fa7681a3d20..1b33cad24abc 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -345,26 +345,26 @@ static void add_files(struct ieee80211_sub_if_data *sdata) return; switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: #ifdef CONFIG_MAC80211_MESH add_mesh_stats(sdata); add_mesh_config(sdata); #endif break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: add_sta_files(sdata); break; - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: add_ap_files(sdata); break; - case IEEE80211_IF_TYPE_WDS: + case NL80211_IFTYPE_WDS: add_wds_files(sdata); break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: add_monitor_files(sdata); break; - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP_VLAN: add_vlan_files(sdata); break; default: @@ -482,26 +482,26 @@ static void del_files(struct ieee80211_sub_if_data *sdata) return; switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: #ifdef CONFIG_MAC80211_MESH del_mesh_stats(sdata); del_mesh_config(sdata); #endif break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: del_sta_files(sdata); break; - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: del_ap_files(sdata); break; - case IEEE80211_IF_TYPE_WDS: + case NL80211_IFTYPE_WDS: del_wds_files(sdata); break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: del_monitor_files(sdata); break; - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP_VLAN: del_vlan_files(sdata); break; default: diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 4dc35c9dabc7..bc3c71ad7ae3 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -89,7 +89,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP) memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); @@ -139,7 +139,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP) memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); @@ -185,7 +185,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP) memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 21cc6d07b020..80d88f5ff90c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -954,10 +954,10 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, /* interface handling */ void ieee80211_if_setup(struct net_device *dev); int ieee80211_if_add(struct ieee80211_local *local, const char *name, - struct net_device **new_dev, enum ieee80211_if_types type, + struct net_device **new_dev, enum nl80211_iftype type, struct vif_params *params); int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, - enum ieee80211_if_types type); + enum nl80211_iftype type); void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); void ieee80211_remove_interfaces(struct ieee80211_local *local); @@ -1001,7 +1001,7 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */ extern const unsigned char rfc1042_header[6]; extern const unsigned char bridge_tunnel_header[6]; u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, - enum ieee80211_if_types type); + enum nl80211_iftype type); int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, int rate, int erp, int short_preamble); void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index dab8eba2602f..004fb23241da 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -41,7 +41,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) sdata->fragment_next = 0; switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: beacon = sdata->u.ap.beacon; rcu_assign_pointer(sdata->u.ap.beacon, NULL); synchronize_rcu(); @@ -53,22 +53,23 @@ static void ieee80211_teardown_sdata(struct net_device *dev) } break; - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_rmc_free(sdata); break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: kfree(sdata->u.sta.extra_ie); kfree(sdata->u.sta.assocreq_ies); kfree(sdata->u.sta.assocresp_ies); kfree_skb(sdata->u.sta.probe_resp); break; - case IEEE80211_IF_TYPE_WDS: - case IEEE80211_IF_TYPE_VLAN: - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: break; - case IEEE80211_IF_TYPE_INVALID: + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: BUG(); break; } @@ -81,7 +82,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) * Helper function to initialise an interface to a specific type. */ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, - enum ieee80211_if_types type) + enum nl80211_iftype type) { /* clear type-dependent union */ memset(&sdata->u, 0, sizeof(sdata->u)); @@ -93,28 +94,29 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, sdata->dev->type = ARPHRD_ETHER; switch (type) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: skb_queue_head_init(&sdata->u.ap.ps_bc_buf); INIT_LIST_HEAD(&sdata->u.ap.vlans); break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: ieee80211_sta_setup_sdata(sdata); break; - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) ieee80211_mesh_init_sdata(sdata); break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | MONITOR_FLAG_OTHER_BSS; break; - case IEEE80211_IF_TYPE_WDS: - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_AP_VLAN: break; - case IEEE80211_IF_TYPE_INVALID: + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: BUG(); break; } @@ -123,7 +125,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, } int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, - enum ieee80211_if_types type) + enum nl80211_iftype type) { ASSERT_RTNL(); @@ -153,7 +155,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, } int ieee80211_if_add(struct ieee80211_local *local, const char *name, - struct net_device **new_dev, enum ieee80211_if_types type, + struct net_device **new_dev, enum nl80211_iftype type, struct vif_params *params) { struct net_device *ndev; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6597c779e35a..d5b95748db2a 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -118,8 +118,8 @@ static const u8 *get_mac_for_key(struct ieee80211_key *key) * address to indicate a transmit-only key. */ if (key->conf.alg != ALG_WEP && - (key->sdata->vif.type == IEEE80211_IF_TYPE_AP || - key->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) + (key->sdata->vif.type == NL80211_IFTYPE_AP || + key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) addr = zero_addr; if (key->sta) @@ -331,7 +331,7 @@ void ieee80211_key_link(struct ieee80211_key *key, */ key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; } else { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->vif.type == NL80211_IFTYPE_STATION) { struct sta_info *ap; /* diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 4c424acc01a4..584a75bd6cfe 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -146,7 +146,7 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) int meshhdrlen; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0; + meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; /* FIX: what would be proper limits for MTU? * This interface uses 802.3 frames. */ @@ -164,18 +164,16 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) static inline int identical_mac_addr_allowed(int type1, int type2) { - return (type1 == IEEE80211_IF_TYPE_MNTR || - type2 == IEEE80211_IF_TYPE_MNTR || - (type1 == IEEE80211_IF_TYPE_AP && - type2 == IEEE80211_IF_TYPE_WDS) || - (type1 == IEEE80211_IF_TYPE_WDS && - (type2 == IEEE80211_IF_TYPE_WDS || - type2 == IEEE80211_IF_TYPE_AP)) || - (type1 == IEEE80211_IF_TYPE_AP && - type2 == IEEE80211_IF_TYPE_VLAN) || - (type1 == IEEE80211_IF_TYPE_VLAN && - (type2 == IEEE80211_IF_TYPE_AP || - type2 == IEEE80211_IF_TYPE_VLAN))); + return type1 == NL80211_IFTYPE_MONITOR || + type2 == NL80211_IFTYPE_MONITOR || + (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || + (type1 == NL80211_IFTYPE_WDS && + (type2 == NL80211_IFTYPE_WDS || + type2 == NL80211_IFTYPE_AP)) || + (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) || + (type1 == NL80211_IFTYPE_AP_VLAN && + (type2 == NL80211_IFTYPE_AP || + type2 == NL80211_IFTYPE_AP_VLAN)); } static int ieee80211_open(struct net_device *dev) @@ -211,8 +209,8 @@ static int ieee80211_open(struct net_device *dev) * belonging to the same hardware. Then, however, we're * faced with having to adopt two different TSF timers... */ - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && - nsdata->vif.type == IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + nsdata->vif.type == NL80211_IFTYPE_ADHOC) return -EBUSY; /* @@ -232,37 +230,38 @@ static int ieee80211_open(struct net_device *dev) /* * can only add VLANs to enabled APs */ - if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && - nsdata->vif.type == IEEE80211_IF_TYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + nsdata->vif.type == NL80211_IFTYPE_AP) sdata->bss = &nsdata->u.ap; } } switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_WDS: + case NL80211_IFTYPE_WDS: if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) return -ENOLINK; break; - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP_VLAN: if (!sdata->bss) return -ENOLINK; list_add(&sdata->u.vlan.list, &sdata->bss->vlans); break; - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: sdata->bss = &sdata->u.ap; break; - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: if (!ieee80211_vif_is_mesh(&sdata->vif)) break; /* mesh ifaces must set allmulti to forward mcast traffic */ atomic_inc(&local->iff_allmultis); break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_MNTR: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_ADHOC: /* no special treatment */ break; - case IEEE80211_IF_TYPE_INVALID: + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: /* cannot happen */ WARN_ON(1); break; @@ -309,10 +308,10 @@ static int ieee80211_open(struct net_device *dev) } switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP_VLAN: /* no need to tell driver */ break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { local->cooked_mntrs++; break; @@ -336,8 +335,8 @@ static int ieee80211_open(struct net_device *dev) ieee80211_configure_filter(local); netif_addr_unlock_bh(local->mdev); break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; /* fall through */ default: @@ -354,14 +353,14 @@ static int ieee80211_open(struct net_device *dev) ieee80211_bss_info_change_notify(sdata, changed); ieee80211_enable_keys(sdata); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA && + if (sdata->vif.type == NL80211_IFTYPE_STATION && !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) netif_carrier_off(dev); else netif_carrier_on(dev); } - if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { + if (sdata->vif.type == NL80211_IFTYPE_WDS) { /* Create STA entry for the WDS peer */ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, GFP_KERNEL); @@ -417,8 +416,8 @@ static int ieee80211_open(struct net_device *dev) * yet be effective. Trigger execution of ieee80211_sta_work * to fix this. */ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; queue_work(local->hw.workqueue, &ifsta->work); } @@ -433,7 +432,7 @@ static int ieee80211_open(struct net_device *dev) local->ops->stop(local_to_hw(local)); err_del_bss: sdata->bss = NULL; - if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) list_del(&sdata->u.vlan.list); return res; } @@ -496,7 +495,7 @@ static int ieee80211_stop(struct net_device *dev) dev_mc_unsync(local->mdev, dev); /* APs need special treatment */ - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { + if (sdata->vif.type == NL80211_IFTYPE_AP) { struct ieee80211_sub_if_data *vlan, *tmp; struct beacon_data *old_beacon = sdata->u.ap.beacon; @@ -515,11 +514,11 @@ static int ieee80211_stop(struct net_device *dev) local->open_count--; switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP_VLAN: list_del(&sdata->u.vlan.list); /* no need to tell driver */ break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { local->cooked_mntrs--; break; @@ -542,8 +541,8 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_configure_filter(local); netif_addr_unlock_bh(local->mdev); break; - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; memset(sdata->u.sta.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.sta.timer); @@ -569,7 +568,7 @@ static int ieee80211_stop(struct net_device *dev) sdata->u.sta.extra_ie = NULL; sdata->u.sta.extra_ie_len = 0; /* fall through */ - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) { /* allmulti is always set on mesh ifaces */ atomic_dec(&local->iff_allmultis); @@ -698,12 +697,12 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) memset(&conf, 0, sizeof(conf)); conf.changed = changed; - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { conf.bssid = sdata->u.sta.bssid; conf.ssid = sdata->u.sta.ssid; conf.ssid_len = sdata->u.sta.ssid_len; - } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { + } else if (sdata->vif.type == NL80211_IFTYPE_AP) { conf.bssid = sdata->dev->dev_addr; conf.ssid = sdata->u.ap.ssid; conf.ssid_len = sdata->u.ap.ssid_len; @@ -1204,7 +1203,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { if (!netif_running(sdata->dev)) continue; @@ -1450,7 +1449,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) /* add one default STA interface */ result = ieee80211_if_add(local, "wlan%d", NULL, - IEEE80211_IF_TYPE_STA, NULL); + NL80211_IFTYPE_STATION, NULL); if (result) printk(KERN_WARNING "%s: Failed to add default virtual iface\n", wiphy_name(local->hw.wiphy)); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 55bc60713937..8a2cfd3609b5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -678,7 +678,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ifsta->flags |= IEEE80211_STA_ASSOCIATED; - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return; bss = ieee80211_rx_bss_get(local, ifsta->bssid, @@ -1002,17 +1002,17 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, DECLARE_MAC_BUF(mac); if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + sdata->vif.type != NL80211_IFTYPE_ADHOC) return; if (len < 24 + 6) return; - if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + if (sdata->vif.type != NL80211_IFTYPE_ADHOC && memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) return; - if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + if (sdata->vif.type != NL80211_IFTYPE_ADHOC && memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; @@ -1020,7 +1020,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); status_code = le16_to_cpu(mgmt->u.auth.status_code); - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { /* * IEEE 802.11 standard does not require authentication in IBSS * networks and most implementations do not seem to use it. @@ -1487,7 +1487,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) return; - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { supp_rates = ieee80211_sta_get_rates(local, elems, band); @@ -1532,14 +1532,14 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * In STA mode, the remaining parameters should not be overridden * by beacons because they're not necessarily accurate there. */ - if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + if (sdata->vif.type != NL80211_IFTYPE_ADHOC && bss->last_probe_resp && beacon) { ieee80211_rx_bss_put(local, bss); return; } /* check if we need to merge IBSS */ - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && bss->capability & WLAN_CAPABILITY_IBSS && bss->freq == local->oper_channel->center_freq && elems->ssid_len == sdata->u.sta.ssid_len && @@ -1649,7 +1649,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return; ifsta = &sdata->u.sta; @@ -1700,7 +1700,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, DECLARE_MAC_BUF(mac3); #endif - if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS || + if (sdata->vif.type != NL80211_IFTYPE_ADHOC || ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || len < 24 + 2 || !ifsta->probe_resp) return; @@ -2212,8 +2212,8 @@ static void ieee80211_sta_work(struct work_struct *work) if (local->sw_scanning || local->hw_scanning) return; - if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC)) return; ifsta = &sdata->u.sta; @@ -2273,7 +2273,7 @@ static void ieee80211_sta_work(struct work_struct *work) static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) + if (sdata->vif.type == NL80211_IFTYPE_STATION) queue_work(sdata->local->hw.workqueue, &sdata->u.sta.work); } @@ -2355,7 +2355,7 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return; if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | @@ -2407,7 +2407,7 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size else ifsta->flags &= ~IEEE80211_STA_SSID_SET; - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { ifsta->ibss_join_req = jiffies; ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; @@ -2482,8 +2482,8 @@ int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", sdata->dev->name, reason); - if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) return -EINVAL; ieee80211_set_disassoc(sdata, ifsta, true, true, reason); @@ -2497,7 +2497,7 @@ int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", sdata->dev->name, reason); - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EINVAL; if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) @@ -2513,7 +2513,7 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) struct ieee80211_sub_if_data *sdata = local->scan_sdata; struct ieee80211_if_sta *ifsta; - if (sdata && sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && @@ -2539,7 +2539,7 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, case IEEE80211_NOTIFY_RE_ASSOC: rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; ieee80211_sta_req_auth(sdata, &sdata->u.sta); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 33530b29c422..8c3dda5f00b2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -295,7 +295,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, if (!netif_running(sdata->dev)) continue; - if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR) + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) continue; if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) @@ -512,7 +512,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) if (unlikely((ieee80211_is_data(hdr->frame_control) || ieee80211_is_pspoll(hdr->frame_control)) && - rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { if ((!ieee80211_has_fromds(hdr->frame_control) && !ieee80211_has_tods(hdr->frame_control) && @@ -724,14 +724,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) /* Update last_rx only for IBSS packets which are for the current * BSSID to avoid keeping the current IBSS network alive in cases where * other STAs are using different BSSID. */ - if (rx->sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, - IEEE80211_IF_TYPE_IBSS); + NL80211_IFTYPE_ADHOC); if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) sta->last_rx = jiffies; } else if (!is_multicast_ether_addr(hdr->addr1) || - rx->sdata->vif.type == IEEE80211_IF_TYPE_STA) { + rx->sdata->vif.type == NL80211_IFTYPE_STATION) { /* Update last_rx only for unicast frames in order to prevent * the Probe Request frames (the only broadcast frames from a * STA in infrastructure mode) from keeping a connection alive. @@ -751,8 +751,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) sta->last_noise = rx->status->noise; if (!ieee80211_has_morefrags(hdr->frame_control) && - (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP || - rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) { + (rx->sdata->vif.type == NL80211_IFTYPE_AP || + rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { /* Change STA power saving mode only in the end of a frame * exchange sequence */ if (test_sta_flags(sta, WLAN_STA_PS) && @@ -982,8 +982,8 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) !(rx->flags & IEEE80211_RX_RA_MATCH))) return RX_CONTINUE; - if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) && - (sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) + if ((sdata->vif.type != NL80211_IFTYPE_AP) && + (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) return RX_DROP_UNUSABLE; skb = skb_dequeue(&rx->sta->tx_filtered); @@ -1131,23 +1131,23 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) switch (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): - if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP && - sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) + if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && + sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) return -1; break; case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): - if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) + if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && + sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) return -1; break; case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): - if (sdata->vif.type != IEEE80211_IF_TYPE_STA || + if (sdata->vif.type != NL80211_IFTYPE_STATION || (is_multicast_ether_addr(dst) && !compare_ether_addr(src, dev->dev_addr))) return -1; break; case __constant_cpu_to_le16(0): - if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type != NL80211_IFTYPE_ADHOC) return -1; break; } @@ -1221,8 +1221,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) skb = rx->skb; xmit_skb = NULL; - if ((sdata->vif.type == IEEE80211_IF_TYPE_AP || - sdata->vif.type == IEEE80211_IF_TYPE_VLAN) && + if ((sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && (rx->flags & IEEE80211_RX_RA_MATCH)) { if (is_multicast_ether_addr(ehdr->h_dest)) { @@ -1536,8 +1536,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) * FIXME: revisit this, I'm sure we should handle most * of these frames in other modes as well! */ - if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) return RX_DROP_MONITOR; switch (mgmt->u.action.category) { @@ -1595,8 +1595,8 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) if (ieee80211_vif_is_mesh(&sdata->vif)) return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); - if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) return RX_DROP_MONITOR; if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) @@ -1632,7 +1632,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, if (!ieee80211_has_protected(hdr->frame_control)) goto ignore; - if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) { + if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { /* * APs with pairwise keys should never receive Michael MIC * errors for non-zero keyidx because these are reserved for @@ -1702,7 +1702,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) if (!netif_running(sdata->dev)) continue; - if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || + if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) continue; @@ -1801,7 +1801,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, int multicast = is_multicast_ether_addr(hdr->addr1); switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: if (!bssid) return 0; if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { @@ -1816,7 +1816,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, rx->flags &= ~IEEE80211_RX_RA_MATCH; } break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: if (!bssid) return 0; if (ieee80211_is_beacon(hdr->frame_control)) { @@ -1837,7 +1837,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, bssid, hdr->addr2, BIT(rx->status->rate_idx)); break; - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: if (!multicast && compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { @@ -1847,8 +1847,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, rx->flags &= ~IEEE80211_RX_RA_MATCH; } break; - case IEEE80211_IF_TYPE_VLAN: - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_AP: if (!bssid) { if (compare_ether_addr(sdata->dev->dev_addr, hdr->addr1)) @@ -1860,16 +1860,17 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, rx->flags &= ~IEEE80211_RX_RA_MATCH; } break; - case IEEE80211_IF_TYPE_WDS: + case NL80211_IFTYPE_WDS: if (bssid || !ieee80211_is_data(hdr->frame_control)) return 0; if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) return 0; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: /* take everything */ break; - case IEEE80211_IF_TYPE_INVALID: + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: /* should never get here */ WARN_ON(1); break; @@ -1930,7 +1931,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (!netif_running(sdata->dev)) continue; - if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) continue; bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5e719e7b720b..8e6685e7ae85 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -475,7 +475,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { /* Tell AP we're back */ - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { ieee80211_send_nullfunc(local, sdata, 0); netif_tx_wake_all_queues(sdata->dev); @@ -539,7 +539,7 @@ void ieee80211_scan_work(struct work_struct *work) chan = &sband->channels[local->scan_channel_idx]; if (chan->flags & IEEE80211_CHAN_DISABLED || - (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + (sdata->vif.type == NL80211_IFTYPE_ADHOC && chan->flags & IEEE80211_CHAN_NO_IBSS)) skip = 1; @@ -638,7 +638,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { netif_tx_stop_all_queues(sdata->dev); ieee80211_send_nullfunc(local, sdata, 1); @@ -681,7 +681,7 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return ieee80211_start_scan(sdata, ssid, ssid_len); /* diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 3370b2625633..31246d8e5327 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -319,7 +319,7 @@ int sta_info_insert(struct sta_info *sta) /* notify driver */ if (local->ops->sta_notify) { - if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); @@ -456,7 +456,7 @@ static void __sta_info_unlink(struct sta_info **sta) local->num_sta--; if (local->ops->sta_notify) { - if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a523189f10c4..f4bcc589d674 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -226,7 +226,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) !ieee80211_is_probe_req(hdr->frame_control)) return TX_DROP; - if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) + if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) return TX_CONTINUE; if (tx->flags & IEEE80211_TX_PS_BUFFERED) @@ -236,7 +236,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (likely(tx->flags & IEEE80211_TX_UNICAST)) { if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && - tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && + tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && ieee80211_is_data(hdr->frame_control))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG DECLARE_MAC_BUF(mac); @@ -250,7 +250,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) } else { if (unlikely(ieee80211_is_data(hdr->frame_control) && tx->local->num_sta == 0 && - tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) { + tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { /* * No associated STAs - no need to send multicast * frames. @@ -281,7 +281,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) list_for_each_entry_rcu(sdata, &local->interfaces, list) { struct ieee80211_if_ap *ap; - if (sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_AP) continue; ap = &sdata->u.ap; skb = skb_dequeue(&ap->ps_bc_buf); @@ -979,7 +979,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, /* process and remove the injection radiotap header */ sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) { + if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) return TX_DROP; @@ -1457,8 +1457,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_AP: - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); /* DA BSSID SA */ memcpy(hdr.addr1, skb->data, ETH_ALEN); @@ -1466,7 +1466,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); hdrlen = 24; break; - case IEEE80211_IF_TYPE_WDS: + case NL80211_IFTYPE_WDS: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); @@ -1476,7 +1476,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, hdrlen = 30; break; #ifdef CONFIG_MAC80211_MESH - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_MESH_POINT: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ memset(hdr.addr1, 0, ETH_ALEN); @@ -1493,7 +1493,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, hdrlen = 30; break; #endif - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: fc |= cpu_to_le16(IEEE80211_FCTL_TODS); /* BSSID SA DA */ memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); @@ -1501,7 +1501,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, memcpy(hdr.addr3, skb->data, ETH_ALEN); hdrlen = 24; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: /* DA SA BSSID */ memcpy(hdr.addr1, skb->data, ETH_ALEN); memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); @@ -1812,7 +1812,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, sdata = vif_to_sdata(vif); bdev = sdata->dev; - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { + if (sdata->vif.type == NL80211_IFTYPE_AP) { ap = &sdata->u.ap; beacon = rcu_dereference(ap->beacon); if (ap && beacon) { @@ -1854,7 +1854,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, num_beacons = &ap->num_beacons; } else goto out; - } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_hdr *hdr; ifsta = &sdata->u.sta; @@ -1999,7 +1999,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, rcu_read_lock(); beacon = rcu_dereference(bss->beacon); - if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head) + if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) goto out; if (bss->dtim_count != 0) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d6aca91e612d..6eb222369bcb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -43,7 +43,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, - enum ieee80211_if_types type) + enum nl80211_iftype type) { __le16 fc = hdr->frame_control; @@ -77,10 +77,10 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, if (ieee80211_is_back_req(fc)) { switch (type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: return hdr->addr2; - case IEEE80211_IF_TYPE_AP: - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: return hdr->addr1; default: break; /* fall through to the return */ @@ -376,15 +376,16 @@ void ieee80211_iterate_active_interfaces( list_for_each_entry(sdata, &local->interfaces, list) { switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_INVALID: - case IEEE80211_IF_TYPE_MNTR: - case IEEE80211_IF_TYPE_VLAN: + case __NL80211_IFTYPE_AFTER_LAST: + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_AP_VLAN: continue; - case IEEE80211_IF_TYPE_AP: - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - case IEEE80211_IF_TYPE_WDS: - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_MESH_POINT: break; } if (netif_running(sdata->dev)) @@ -409,15 +410,16 @@ void ieee80211_iterate_active_interfaces_atomic( list_for_each_entry_rcu(sdata, &local->interfaces, list) { switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_INVALID: - case IEEE80211_IF_TYPE_MNTR: - case IEEE80211_IF_TYPE_VLAN: + case __NL80211_IFTYPE_AFTER_LAST: + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_AP_VLAN: continue; - case IEEE80211_IF_TYPE_AP: - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - case IEEE80211_IF_TYPE_WDS: - case IEEE80211_IF_TYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_MESH_POINT: break; } if (netif_running(sdata->dev)) @@ -622,7 +624,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && chan->flags & IEEE80211_CHAN_NO_IBSS) { printk(KERN_DEBUG "%s: IBSS not allowed on frequency " "%d MHz\n", sdata->dev->name, chan->center_freq); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 77b68ed8b832..aef9707700fd 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -122,8 +122,8 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) return -EOPNOTSUPP; - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); if (ret) return ret; @@ -273,21 +273,21 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int type; - if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) return -EOPNOTSUPP; switch (*mode) { case IW_MODE_INFRA: - type = IEEE80211_IF_TYPE_STA; + type = NL80211_IFTYPE_STATION; break; case IW_MODE_ADHOC: - type = IEEE80211_IF_TYPE_IBSS; + type = NL80211_IFTYPE_ADHOC; break; case IW_MODE_REPEAT: - type = IEEE80211_IF_TYPE_WDS; + type = NL80211_IFTYPE_WDS; break; case IW_MODE_MONITOR: - type = IEEE80211_IF_TYPE_MNTR; + type = NL80211_IFTYPE_MONITOR; break; default: return -EINVAL; @@ -305,22 +305,22 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); switch (sdata->vif.type) { - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: *mode = IW_MODE_MASTER; break; - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: *mode = IW_MODE_INFRA; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: *mode = IW_MODE_ADHOC; break; - case IEEE80211_IF_TYPE_MNTR: + case NL80211_IFTYPE_MONITOR: *mode = IW_MODE_MONITOR; break; - case IEEE80211_IF_TYPE_WDS: + case NL80211_IFTYPE_WDS: *mode = IW_MODE_REPEAT; break; - case IEEE80211_IF_TYPE_VLAN: + case NL80211_IFTYPE_AP_VLAN: *mode = IW_MODE_SECOND; /* FIXME */ break; default: @@ -336,13 +336,13 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) + if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ if (freq->e == 0) { if (freq->m < 0) { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) + if (sdata->vif.type == NL80211_IFTYPE_STATION) sdata->u.sta.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; @@ -386,8 +386,8 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, len--; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { int ret; if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { if (len > IEEE80211_MAX_SSID_LEN) @@ -407,7 +407,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, return 0; } - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { + if (sdata->vif.type == NL80211_IFTYPE_AP) { memcpy(sdata->u.ap.ssid, ssid, len); memset(sdata->u.ap.ssid + len, 0, IEEE80211_MAX_SSID_LEN - len); @@ -426,8 +426,8 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { int res = ieee80211_sta_get_ssid(sdata, ssid, &len); if (res == 0) { data->length = len; @@ -437,7 +437,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, return res; } - if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { + if (sdata->vif.type == NL80211_IFTYPE_AP) { len = sdata->u.ap.ssid_len; if (len > IW_ESSID_MAX_SIZE) len = IW_ESSID_MAX_SIZE; @@ -457,8 +457,8 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { int ret; if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data, @@ -477,7 +477,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, return ret; ieee80211_sta_req_auth(sdata, &sdata->u.sta); return 0; - } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { + } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { /* * If it is necessary to update the WDS peer address * while the interface is running, then we need to do @@ -505,8 +505,8 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED || sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) { ap_addr->sa_family = ARPHRD_ETHER; @@ -516,7 +516,7 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, memset(&ap_addr->sa_data, 0, ETH_ALEN); return 0; } - } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { + } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { ap_addr->sa_family = ARPHRD_ETHER; memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); return 0; @@ -538,10 +538,10 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, if (!netif_running(dev)) return -ENETDOWN; - if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT && - sdata->vif.type != IEEE80211_IF_TYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC && + sdata->vif.type != NL80211_IFTYPE_MESH_POINT && + sdata->vif.type != NL80211_IFTYPE_AP) return -EOPNOTSUPP; /* if SSID was specified explicitly then use that */ @@ -627,7 +627,7 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; @@ -858,8 +858,8 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev, struct iw_mlme *mlme = (struct iw_mlme *) extra; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) return -EINVAL; switch (mlme->cmd) { @@ -954,7 +954,7 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, erq->length = sdata->keys[idx]->conf.keylen; erq->flags |= IW_ENCODE_ENABLED; - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { + if (sdata->vif.type == NL80211_IFTYPE_STATION) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; switch (ifsta->auth_alg) { case WLAN_AUTH_OPEN: @@ -1028,7 +1028,7 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, sdata->drop_unencrypted = !!data->value; break; case IW_AUTH_PRIVACY_INVOKED: - if (sdata->vif.type != IEEE80211_IF_TYPE_STA) + if (sdata->vif.type != NL80211_IFTYPE_STATION) ret = -EINVAL; else { sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; @@ -1043,8 +1043,8 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, } break; case IW_AUTH_80211_AUTH_ALG: - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) sdata->u.sta.auth_algs = data->value; else ret = -EOPNOTSUPP; @@ -1066,8 +1066,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev rcu_read_lock(); - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) sta = sta_info_get(local, sdata->u.sta.bssid); if (!sta) { wstats->discard.fragment = 0; @@ -1097,8 +1097,8 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev, switch (data->flags & IW_AUTH_INDEX) { case IW_AUTH_80211_AUTH_ALG: - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - sdata->vif.type == IEEE80211_IF_TYPE_IBSS) + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) data->value = sdata->u.sta.auth_algs; else ret = -EOPNOTSUPP; -- cgit v1.2.3 From 0d143fe1e2efc084fa730d2dfa22d0d1ca2ee5f1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:59 +0200 Subject: mac80211: move regular interface handling Move the code to handle regular interfaces out of main.c and into iface.c, keep only the master interface stuff in main.c. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/iface.c | 534 ++++++++++++++++++++++++++++++++++++++++++ net/mac80211/main.c | 565 ++------------------------------------------- 3 files changed, 550 insertions(+), 551 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 80d88f5ff90c..6bd6a6306da3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -891,6 +891,7 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_bss_info *req_bss_cap); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); +void ieee80211_configure_filter(struct ieee80211_local *local); /* wireless extensions */ extern const struct iw_handler_def ieee80211_iw_handler_def; @@ -952,7 +953,6 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss); /* interface handling */ -void ieee80211_if_setup(struct net_device *dev); int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct net_device **new_dev, enum nl80211_iftype type, struct vif_params *params); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 004fb23241da..f528962b13e3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1,4 +1,6 @@ /* + * Interface handling (except master interface) + * * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright (c) 2006 Jiri Benc @@ -17,7 +19,539 @@ #include "sta_info.h" #include "debugfs_netdev.h" #include "mesh.h" +#include "led.h" + +static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +{ + int meshhdrlen; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; + + /* FIX: what would be proper limits for MTU? + * This interface uses 802.3 frames. */ + if (new_mtu < 256 || + new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { + return -EINVAL; + } + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); +#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ + dev->mtu = new_mtu; + return 0; +} + +static inline int identical_mac_addr_allowed(int type1, int type2) +{ + return type1 == NL80211_IFTYPE_MONITOR || + type2 == NL80211_IFTYPE_MONITOR || + (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || + (type1 == NL80211_IFTYPE_WDS && + (type2 == NL80211_IFTYPE_WDS || + type2 == NL80211_IFTYPE_AP)) || + (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) || + (type1 == NL80211_IFTYPE_AP_VLAN && + (type2 == NL80211_IFTYPE_AP || + type2 == NL80211_IFTYPE_AP_VLAN)); +} + +static int ieee80211_open(struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata, *nsdata; + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct sta_info *sta; + struct ieee80211_if_init_conf conf; + u32 changed = 0; + int res; + bool need_hw_reconfig = 0; + u8 null_addr[ETH_ALEN] = {0}; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + /* fail early if user set an invalid address */ + if (compare_ether_addr(dev->dev_addr, null_addr) && + !is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + /* we hold the RTNL here so can safely walk the list */ + list_for_each_entry(nsdata, &local->interfaces, list) { + struct net_device *ndev = nsdata->dev; + + if (ndev != dev && netif_running(ndev)) { + /* + * Allow only a single IBSS interface to be up at any + * time. This is restricted because beacon distribution + * cannot work properly if both are in the same IBSS. + * + * To remove this restriction we'd have to disallow them + * from setting the same SSID on different IBSS interfaces + * belonging to the same hardware. Then, however, we're + * faced with having to adopt two different TSF timers... + */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + nsdata->vif.type == NL80211_IFTYPE_ADHOC) + return -EBUSY; + + /* + * The remaining checks are only performed for interfaces + * with the same MAC address. + */ + if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) + continue; + + /* + * check whether it may have the same address + */ + if (!identical_mac_addr_allowed(sdata->vif.type, + nsdata->vif.type)) + return -ENOTUNIQ; + + /* + * can only add VLANs to enabled APs + */ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + nsdata->vif.type == NL80211_IFTYPE_AP) + sdata->bss = &nsdata->u.ap; + } + } + + switch (sdata->vif.type) { + case NL80211_IFTYPE_WDS: + if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) + return -ENOLINK; + break; + case NL80211_IFTYPE_AP_VLAN: + if (!sdata->bss) + return -ENOLINK; + list_add(&sdata->u.vlan.list, &sdata->bss->vlans); + break; + case NL80211_IFTYPE_AP: + sdata->bss = &sdata->u.ap; + break; + case NL80211_IFTYPE_MESH_POINT: + if (!ieee80211_vif_is_mesh(&sdata->vif)) + break; + /* mesh ifaces must set allmulti to forward mcast traffic */ + atomic_inc(&local->iff_allmultis); + break; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_MONITOR: + case NL80211_IFTYPE_ADHOC: + /* no special treatment */ + break; + case NL80211_IFTYPE_UNSPECIFIED: + case __NL80211_IFTYPE_AFTER_LAST: + /* cannot happen */ + WARN_ON(1); + break; + } + + if (local->open_count == 0) { + res = 0; + if (local->ops->start) + res = local->ops->start(local_to_hw(local)); + if (res) + goto err_del_bss; + need_hw_reconfig = 1; + ieee80211_led_radio(local, local->hw.conf.radio_enabled); + } + /* + * Check all interfaces and copy the hopefully now-present + * MAC address to those that have the special null one. + */ + list_for_each_entry(nsdata, &local->interfaces, list) { + struct net_device *ndev = nsdata->dev; + + /* + * No need to check netif_running since we do not allow + * it to start up with this invalid address. + */ + if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) + memcpy(ndev->dev_addr, + local->hw.wiphy->perm_addr, + ETH_ALEN); + } + + if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) + memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, + ETH_ALEN); + + /* + * Validate the MAC address for this device. + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + if (!local->open_count && local->ops->stop) + local->ops->stop(local_to_hw(local)); + return -EADDRNOTAVAIL; + } + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + /* no need to tell driver */ + break; + case NL80211_IFTYPE_MONITOR: + if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { + local->cooked_mntrs++; + break; + } + + /* must be before the call to ieee80211_configure_filter */ + local->monitors++; + if (local->monitors == 1) + local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; + + if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) + local->fif_fcsfail++; + if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) + local->fif_plcpfail++; + if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) + local->fif_control++; + if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) + local->fif_other_bss++; + + netif_addr_lock_bh(local->mdev); + ieee80211_configure_filter(local); + netif_addr_unlock_bh(local->mdev); + break; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; + /* fall through */ + default: + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = dev->dev_addr; + res = local->ops->add_interface(local_to_hw(local), &conf); + if (res) + goto err_stop; + + if (ieee80211_vif_is_mesh(&sdata->vif)) + ieee80211_start_mesh(sdata); + changed |= ieee80211_reset_erp_info(sdata); + ieee80211_bss_info_change_notify(sdata, changed); + ieee80211_enable_keys(sdata); + + if (sdata->vif.type == NL80211_IFTYPE_STATION && + !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) + netif_carrier_off(dev); + else + netif_carrier_on(dev); + } + + if (sdata->vif.type == NL80211_IFTYPE_WDS) { + /* Create STA entry for the WDS peer */ + sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, + GFP_KERNEL); + if (!sta) { + res = -ENOMEM; + goto err_del_interface; + } + + /* no locking required since STA is not live yet */ + sta->flags |= WLAN_STA_AUTHORIZED; + + res = sta_info_insert(sta); + if (res) { + /* STA has been freed */ + goto err_del_interface; + } + } + + if (local->open_count == 0) { + res = dev_open(local->mdev); + WARN_ON(res); + if (res) + goto err_del_interface; + tasklet_enable(&local->tx_pending_tasklet); + tasklet_enable(&local->tasklet); + } + + /* + * set_multicast_list will be invoked by the networking core + * which will check whether any increments here were done in + * error and sync them down to the hardware as filter flags. + */ + if (sdata->flags & IEEE80211_SDATA_ALLMULTI) + atomic_inc(&local->iff_allmultis); + + if (sdata->flags & IEEE80211_SDATA_PROMISC) + atomic_inc(&local->iff_promiscs); + + local->open_count++; + if (need_hw_reconfig) { + ieee80211_hw_config(local); + /* + * set default queue parameters so drivers don't + * need to initialise the hardware if the hardware + * doesn't start up with sane defaults + */ + ieee80211_set_wmm_default(sdata); + } + + /* + * ieee80211_sta_work is disabled while network interface + * is down. Therefore, some configuration changes may not + * yet be effective. Trigger execution of ieee80211_sta_work + * to fix this. + */ + if (sdata->vif.type == NL80211_IFTYPE_STATION || + sdata->vif.type == NL80211_IFTYPE_ADHOC) { + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + queue_work(local->hw.workqueue, &ifsta->work); + } + + netif_tx_start_all_queues(dev); + + return 0; + err_del_interface: + local->ops->remove_interface(local_to_hw(local), &conf); + err_stop: + if (!local->open_count && local->ops->stop) + local->ops->stop(local_to_hw(local)); + err_del_bss: + sdata->bss = NULL; + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + list_del(&sdata->u.vlan.list); + return res; +} + +static int ieee80211_stop(struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_init_conf conf; + struct sta_info *sta; + + /* + * Stop TX on this interface first. + */ + netif_tx_stop_all_queues(dev); + + /* + * Now delete all active aggregation sessions. + */ + rcu_read_lock(); + + list_for_each_entry_rcu(sta, &local->sta_list, list) { + if (sta->sdata == sdata) + ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); + } + + rcu_read_unlock(); + + /* + * Remove all stations associated with this interface. + * + * This must be done before calling ops->remove_interface() + * because otherwise we can later invoke ops->sta_notify() + * whenever the STAs are removed, and that invalidates driver + * assumptions about always getting a vif pointer that is valid + * (because if we remove a STA after ops->remove_interface() + * the driver will have removed the vif info already!) + * + * We could relax this and only unlink the stations from the + * hash table and list but keep them on a per-sdata list that + * will be inserted back again when the interface is brought + * up again, but I don't currently see a use case for that, + * except with WDS which gets a STA entry created when it is + * brought up. + */ + sta_info_flush(local, sdata); + + /* + * Don't count this interface for promisc/allmulti while it + * is down. dev_mc_unsync() will invoke set_multicast_list + * on the master interface which will sync these down to the + * hardware as filter flags. + */ + if (sdata->flags & IEEE80211_SDATA_ALLMULTI) + atomic_dec(&local->iff_allmultis); + + if (sdata->flags & IEEE80211_SDATA_PROMISC) + atomic_dec(&local->iff_promiscs); + + dev_mc_unsync(local->mdev, dev); + + /* APs need special treatment */ + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan, *tmp; + struct beacon_data *old_beacon = sdata->u.ap.beacon; + + /* remove beacon */ + rcu_assign_pointer(sdata->u.ap.beacon, NULL); + synchronize_rcu(); + kfree(old_beacon); + + /* down all dependent devices, that is VLANs */ + list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, + u.vlan.list) + dev_close(vlan->dev); + WARN_ON(!list_empty(&sdata->u.ap.vlans)); + } + + local->open_count--; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP_VLAN: + list_del(&sdata->u.vlan.list); + /* no need to tell driver */ + break; + case NL80211_IFTYPE_MONITOR: + if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { + local->cooked_mntrs--; + break; + } + + local->monitors--; + if (local->monitors == 0) + local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; + + if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) + local->fif_fcsfail--; + if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) + local->fif_plcpfail--; + if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) + local->fif_control--; + if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) + local->fif_other_bss--; + + netif_addr_lock_bh(local->mdev); + ieee80211_configure_filter(local); + netif_addr_unlock_bh(local->mdev); + break; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; + memset(sdata->u.sta.bssid, 0, ETH_ALEN); + del_timer_sync(&sdata->u.sta.timer); + /* + * If the timer fired while we waited for it, it will have + * requeued the work. Now the work will be running again + * but will not rearm the timer again because it checks + * whether the interface is running, which, at this point, + * it no longer is. + */ + cancel_work_sync(&sdata->u.sta.work); + /* + * When we get here, the interface is marked down. + * Call synchronize_rcu() to wait for the RX path + * should it be using the interface and enqueuing + * frames at this very time on another CPU. + */ + synchronize_rcu(); + skb_queue_purge(&sdata->u.sta.skb_queue); + + sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; + kfree(sdata->u.sta.extra_ie); + sdata->u.sta.extra_ie = NULL; + sdata->u.sta.extra_ie_len = 0; + /* fall through */ + case NL80211_IFTYPE_MESH_POINT: + if (ieee80211_vif_is_mesh(&sdata->vif)) { + /* allmulti is always set on mesh ifaces */ + atomic_dec(&local->iff_allmultis); + ieee80211_stop_mesh(sdata); + } + /* fall through */ + default: + if (local->scan_sdata == sdata) { + if (!local->ops->hw_scan) + cancel_delayed_work_sync(&local->scan_work); + /* + * The software scan can no longer run now, so we can + * clear out the scan_sdata reference. However, the + * hardware scan may still be running. The complete + * function must be prepared to handle a NULL value. + */ + local->scan_sdata = NULL; + /* + * The memory barrier guarantees that another CPU + * that is hardware-scanning will now see the fact + * that this interface is gone. + */ + smp_mb(); + /* + * If software scanning, complete the scan but since + * the scan_sdata is NULL already don't send out a + * scan event to userspace -- the scan is incomplete. + */ + if (local->sw_scanning) + ieee80211_scan_completed(&local->hw); + } + + conf.vif = &sdata->vif; + conf.type = sdata->vif.type; + conf.mac_addr = dev->dev_addr; + /* disable all keys for as long as this netdev is down */ + ieee80211_disable_keys(sdata); + local->ops->remove_interface(local_to_hw(local), &conf); + } + + sdata->bss = NULL; + + if (local->open_count == 0) { + if (netif_running(local->mdev)) + dev_close(local->mdev); + + if (local->ops->stop) + local->ops->stop(local_to_hw(local)); + + ieee80211_led_radio(local, 0); + + flush_workqueue(local->hw.workqueue); + + tasklet_disable(&local->tx_pending_tasklet); + tasklet_disable(&local->tasklet); + } + + return 0; +} + +static void ieee80211_set_multicast_list(struct net_device *dev) +{ + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + int allmulti, promisc, sdata_allmulti, sdata_promisc; + + allmulti = !!(dev->flags & IFF_ALLMULTI); + promisc = !!(dev->flags & IFF_PROMISC); + sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); + sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); + + if (allmulti != sdata_allmulti) { + if (dev->flags & IFF_ALLMULTI) + atomic_inc(&local->iff_allmultis); + else + atomic_dec(&local->iff_allmultis); + sdata->flags ^= IEEE80211_SDATA_ALLMULTI; + } + + if (promisc != sdata_promisc) { + if (dev->flags & IFF_PROMISC) + atomic_inc(&local->iff_promiscs); + else + atomic_dec(&local->iff_promiscs); + sdata->flags ^= IEEE80211_SDATA_PROMISC; + } + + dev_mc_sync(local->mdev, dev); +} + +static void ieee80211_if_setup(struct net_device *dev) +{ + ether_setup(dev); + dev->hard_start_xmit = ieee80211_subif_start_xmit; + dev->wireless_handlers = &ieee80211_iw_handler_def; + dev->set_multicast_list = ieee80211_set_multicast_list; + dev->change_mtu = ieee80211_change_mtu; + dev->open = ieee80211_open; + dev->stop = ieee80211_stop; + dev->destructor = free_netdev; + /* we will validate the address ourselves in ->open */ + dev->validate_addr = NULL; +} /* * Called when the netdev is removed or, by the code below, before * the interface type changes. diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 584a75bd6cfe..c532043c1a1c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -45,16 +45,9 @@ struct ieee80211_tx_status_rtap_hdr { u8 data_retries; } __attribute__ ((packed)); -/* common interface routines */ - -static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) -{ - memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ - return ETH_ALEN; -} /* must be called under mdev tx lock */ -static void ieee80211_configure_filter(struct ieee80211_local *local) +void ieee80211_configure_filter(struct ieee80211_local *local) { unsigned int changed_flags; unsigned int new_flags = 0; @@ -97,6 +90,20 @@ static void ieee80211_configure_filter(struct ieee80211_local *local) /* master interface */ +static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) +{ + memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ + return ETH_ALEN; +} + +static const struct header_ops ieee80211_header_ops = { + .create = eth_header, + .parse = header_parse_80211, + .rebuild = eth_rebuild_header, + .cache = eth_header_cache, + .cache_update = eth_header_cache_update, +}; + static int ieee80211_master_open(struct net_device *dev) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); @@ -139,548 +146,6 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev) ieee80211_configure_filter(local); } -/* regular interfaces */ - -static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) -{ - int meshhdrlen; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; - - /* FIX: what would be proper limits for MTU? - * This interface uses 802.3 frames. */ - if (new_mtu < 256 || - new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { - return -EINVAL; - } - -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - dev->mtu = new_mtu; - return 0; -} - -static inline int identical_mac_addr_allowed(int type1, int type2) -{ - return type1 == NL80211_IFTYPE_MONITOR || - type2 == NL80211_IFTYPE_MONITOR || - (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || - (type1 == NL80211_IFTYPE_WDS && - (type2 == NL80211_IFTYPE_WDS || - type2 == NL80211_IFTYPE_AP)) || - (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) || - (type1 == NL80211_IFTYPE_AP_VLAN && - (type2 == NL80211_IFTYPE_AP || - type2 == NL80211_IFTYPE_AP_VLAN)); -} - -static int ieee80211_open(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata, *nsdata; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct sta_info *sta; - struct ieee80211_if_init_conf conf; - u32 changed = 0; - int res; - bool need_hw_reconfig = 0; - u8 null_addr[ETH_ALEN] = {0}; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - /* fail early if user set an invalid address */ - if (compare_ether_addr(dev->dev_addr, null_addr) && - !is_valid_ether_addr(dev->dev_addr)) - return -EADDRNOTAVAIL; - - /* we hold the RTNL here so can safely walk the list */ - list_for_each_entry(nsdata, &local->interfaces, list) { - struct net_device *ndev = nsdata->dev; - - if (ndev != dev && netif_running(ndev)) { - /* - * Allow only a single IBSS interface to be up at any - * time. This is restricted because beacon distribution - * cannot work properly if both are in the same IBSS. - * - * To remove this restriction we'd have to disallow them - * from setting the same SSID on different IBSS interfaces - * belonging to the same hardware. Then, however, we're - * faced with having to adopt two different TSF timers... - */ - if (sdata->vif.type == NL80211_IFTYPE_ADHOC && - nsdata->vif.type == NL80211_IFTYPE_ADHOC) - return -EBUSY; - - /* - * The remaining checks are only performed for interfaces - * with the same MAC address. - */ - if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) - continue; - - /* - * check whether it may have the same address - */ - if (!identical_mac_addr_allowed(sdata->vif.type, - nsdata->vif.type)) - return -ENOTUNIQ; - - /* - * can only add VLANs to enabled APs - */ - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && - nsdata->vif.type == NL80211_IFTYPE_AP) - sdata->bss = &nsdata->u.ap; - } - } - - switch (sdata->vif.type) { - case NL80211_IFTYPE_WDS: - if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) - return -ENOLINK; - break; - case NL80211_IFTYPE_AP_VLAN: - if (!sdata->bss) - return -ENOLINK; - list_add(&sdata->u.vlan.list, &sdata->bss->vlans); - break; - case NL80211_IFTYPE_AP: - sdata->bss = &sdata->u.ap; - break; - case NL80211_IFTYPE_MESH_POINT: - if (!ieee80211_vif_is_mesh(&sdata->vif)) - break; - /* mesh ifaces must set allmulti to forward mcast traffic */ - atomic_inc(&local->iff_allmultis); - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_ADHOC: - /* no special treatment */ - break; - case NL80211_IFTYPE_UNSPECIFIED: - case __NL80211_IFTYPE_AFTER_LAST: - /* cannot happen */ - WARN_ON(1); - break; - } - - if (local->open_count == 0) { - res = 0; - if (local->ops->start) - res = local->ops->start(local_to_hw(local)); - if (res) - goto err_del_bss; - need_hw_reconfig = 1; - ieee80211_led_radio(local, local->hw.conf.radio_enabled); - } - - /* - * Check all interfaces and copy the hopefully now-present - * MAC address to those that have the special null one. - */ - list_for_each_entry(nsdata, &local->interfaces, list) { - struct net_device *ndev = nsdata->dev; - - /* - * No need to check netif_running since we do not allow - * it to start up with this invalid address. - */ - if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) - memcpy(ndev->dev_addr, - local->hw.wiphy->perm_addr, - ETH_ALEN); - } - - if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) - memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, - ETH_ALEN); - - /* - * Validate the MAC address for this device. - */ - if (!is_valid_ether_addr(dev->dev_addr)) { - if (!local->open_count && local->ops->stop) - local->ops->stop(local_to_hw(local)); - return -EADDRNOTAVAIL; - } - - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP_VLAN: - /* no need to tell driver */ - break; - case NL80211_IFTYPE_MONITOR: - if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { - local->cooked_mntrs++; - break; - } - - /* must be before the call to ieee80211_configure_filter */ - local->monitors++; - if (local->monitors == 1) - local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; - - if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) - local->fif_fcsfail++; - if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) - local->fif_plcpfail++; - if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) - local->fif_control++; - if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) - local->fif_other_bss++; - - netif_addr_lock_bh(local->mdev); - ieee80211_configure_filter(local); - netif_addr_unlock_bh(local->mdev); - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; - /* fall through */ - default: - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = dev->dev_addr; - res = local->ops->add_interface(local_to_hw(local), &conf); - if (res) - goto err_stop; - - if (ieee80211_vif_is_mesh(&sdata->vif)) - ieee80211_start_mesh(sdata); - changed |= ieee80211_reset_erp_info(sdata); - ieee80211_bss_info_change_notify(sdata, changed); - ieee80211_enable_keys(sdata); - - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) - netif_carrier_off(dev); - else - netif_carrier_on(dev); - } - - if (sdata->vif.type == NL80211_IFTYPE_WDS) { - /* Create STA entry for the WDS peer */ - sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, - GFP_KERNEL); - if (!sta) { - res = -ENOMEM; - goto err_del_interface; - } - - /* no locking required since STA is not live yet */ - sta->flags |= WLAN_STA_AUTHORIZED; - - res = sta_info_insert(sta); - if (res) { - /* STA has been freed */ - goto err_del_interface; - } - } - - if (local->open_count == 0) { - res = dev_open(local->mdev); - WARN_ON(res); - if (res) - goto err_del_interface; - tasklet_enable(&local->tx_pending_tasklet); - tasklet_enable(&local->tasklet); - } - - /* - * set_multicast_list will be invoked by the networking core - * which will check whether any increments here were done in - * error and sync them down to the hardware as filter flags. - */ - if (sdata->flags & IEEE80211_SDATA_ALLMULTI) - atomic_inc(&local->iff_allmultis); - - if (sdata->flags & IEEE80211_SDATA_PROMISC) - atomic_inc(&local->iff_promiscs); - - local->open_count++; - if (need_hw_reconfig) { - ieee80211_hw_config(local); - /* - * set default queue parameters so drivers don't - * need to initialise the hardware if the hardware - * doesn't start up with sane defaults - */ - ieee80211_set_wmm_default(sdata); - } - - /* - * ieee80211_sta_work is disabled while network interface - * is down. Therefore, some configuration changes may not - * yet be effective. Trigger execution of ieee80211_sta_work - * to fix this. - */ - if (sdata->vif.type == NL80211_IFTYPE_STATION || - sdata->vif.type == NL80211_IFTYPE_ADHOC) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - queue_work(local->hw.workqueue, &ifsta->work); - } - - netif_tx_start_all_queues(dev); - - return 0; - err_del_interface: - local->ops->remove_interface(local_to_hw(local), &conf); - err_stop: - if (!local->open_count && local->ops->stop) - local->ops->stop(local_to_hw(local)); - err_del_bss: - sdata->bss = NULL; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - list_del(&sdata->u.vlan.list); - return res; -} - -static int ieee80211_stop(struct net_device *dev) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_init_conf conf; - struct sta_info *sta; - - /* - * Stop TX on this interface first. - */ - netif_tx_stop_all_queues(dev); - - /* - * Now delete all active aggregation sessions. - */ - rcu_read_lock(); - - list_for_each_entry_rcu(sta, &local->sta_list, list) { - if (sta->sdata == sdata) - ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); - } - - rcu_read_unlock(); - - /* - * Remove all stations associated with this interface. - * - * This must be done before calling ops->remove_interface() - * because otherwise we can later invoke ops->sta_notify() - * whenever the STAs are removed, and that invalidates driver - * assumptions about always getting a vif pointer that is valid - * (because if we remove a STA after ops->remove_interface() - * the driver will have removed the vif info already!) - * - * We could relax this and only unlink the stations from the - * hash table and list but keep them on a per-sdata list that - * will be inserted back again when the interface is brought - * up again, but I don't currently see a use case for that, - * except with WDS which gets a STA entry created when it is - * brought up. - */ - sta_info_flush(local, sdata); - - /* - * Don't count this interface for promisc/allmulti while it - * is down. dev_mc_unsync() will invoke set_multicast_list - * on the master interface which will sync these down to the - * hardware as filter flags. - */ - if (sdata->flags & IEEE80211_SDATA_ALLMULTI) - atomic_dec(&local->iff_allmultis); - - if (sdata->flags & IEEE80211_SDATA_PROMISC) - atomic_dec(&local->iff_promiscs); - - dev_mc_unsync(local->mdev, dev); - - /* APs need special treatment */ - if (sdata->vif.type == NL80211_IFTYPE_AP) { - struct ieee80211_sub_if_data *vlan, *tmp; - struct beacon_data *old_beacon = sdata->u.ap.beacon; - - /* remove beacon */ - rcu_assign_pointer(sdata->u.ap.beacon, NULL); - synchronize_rcu(); - kfree(old_beacon); - - /* down all dependent devices, that is VLANs */ - list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, - u.vlan.list) - dev_close(vlan->dev); - WARN_ON(!list_empty(&sdata->u.ap.vlans)); - } - - local->open_count--; - - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP_VLAN: - list_del(&sdata->u.vlan.list); - /* no need to tell driver */ - break; - case NL80211_IFTYPE_MONITOR: - if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { - local->cooked_mntrs--; - break; - } - - local->monitors--; - if (local->monitors == 0) - local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; - - if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) - local->fif_fcsfail--; - if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) - local->fif_plcpfail--; - if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) - local->fif_control--; - if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) - local->fif_other_bss--; - - netif_addr_lock_bh(local->mdev); - ieee80211_configure_filter(local); - netif_addr_unlock_bh(local->mdev); - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; - memset(sdata->u.sta.bssid, 0, ETH_ALEN); - del_timer_sync(&sdata->u.sta.timer); - /* - * If the timer fired while we waited for it, it will have - * requeued the work. Now the work will be running again - * but will not rearm the timer again because it checks - * whether the interface is running, which, at this point, - * it no longer is. - */ - cancel_work_sync(&sdata->u.sta.work); - /* - * When we get here, the interface is marked down. - * Call synchronize_rcu() to wait for the RX path - * should it be using the interface and enqueuing - * frames at this very time on another CPU. - */ - synchronize_rcu(); - skb_queue_purge(&sdata->u.sta.skb_queue); - - sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; - kfree(sdata->u.sta.extra_ie); - sdata->u.sta.extra_ie = NULL; - sdata->u.sta.extra_ie_len = 0; - /* fall through */ - case NL80211_IFTYPE_MESH_POINT: - if (ieee80211_vif_is_mesh(&sdata->vif)) { - /* allmulti is always set on mesh ifaces */ - atomic_dec(&local->iff_allmultis); - ieee80211_stop_mesh(sdata); - } - /* fall through */ - default: - if (local->scan_sdata == sdata) { - if (!local->ops->hw_scan) - cancel_delayed_work_sync(&local->scan_work); - /* - * The software scan can no longer run now, so we can - * clear out the scan_sdata reference. However, the - * hardware scan may still be running. The complete - * function must be prepared to handle a NULL value. - */ - local->scan_sdata = NULL; - /* - * The memory barrier guarantees that another CPU - * that is hardware-scanning will now see the fact - * that this interface is gone. - */ - smp_mb(); - /* - * If software scanning, complete the scan but since - * the scan_sdata is NULL already don't send out a - * scan event to userspace -- the scan is incomplete. - */ - if (local->sw_scanning) - ieee80211_scan_completed(&local->hw); - } - - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = dev->dev_addr; - /* disable all keys for as long as this netdev is down */ - ieee80211_disable_keys(sdata); - local->ops->remove_interface(local_to_hw(local), &conf); - } - - sdata->bss = NULL; - - if (local->open_count == 0) { - if (netif_running(local->mdev)) - dev_close(local->mdev); - - if (local->ops->stop) - local->ops->stop(local_to_hw(local)); - - ieee80211_led_radio(local, 0); - - flush_workqueue(local->hw.workqueue); - - tasklet_disable(&local->tx_pending_tasklet); - tasklet_disable(&local->tasklet); - } - - return 0; -} - -static void ieee80211_set_multicast_list(struct net_device *dev) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - int allmulti, promisc, sdata_allmulti, sdata_promisc; - - allmulti = !!(dev->flags & IFF_ALLMULTI); - promisc = !!(dev->flags & IFF_PROMISC); - sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); - sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); - - if (allmulti != sdata_allmulti) { - if (dev->flags & IFF_ALLMULTI) - atomic_inc(&local->iff_allmultis); - else - atomic_dec(&local->iff_allmultis); - sdata->flags ^= IEEE80211_SDATA_ALLMULTI; - } - - if (promisc != sdata_promisc) { - if (dev->flags & IFF_PROMISC) - atomic_inc(&local->iff_promiscs); - else - atomic_dec(&local->iff_promiscs); - sdata->flags ^= IEEE80211_SDATA_PROMISC; - } - - dev_mc_sync(local->mdev, dev); -} - -static const struct header_ops ieee80211_header_ops = { - .create = eth_header, - .parse = header_parse_80211, - .rebuild = eth_rebuild_header, - .cache = eth_header_cache, - .cache_update = eth_header_cache_update, -}; - -void ieee80211_if_setup(struct net_device *dev) -{ - ether_setup(dev); - dev->hard_start_xmit = ieee80211_subif_start_xmit; - dev->wireless_handlers = &ieee80211_iw_handler_def; - dev->set_multicast_list = ieee80211_set_multicast_list; - dev->change_mtu = ieee80211_change_mtu; - dev->open = ieee80211_open; - dev->stop = ieee80211_stop; - dev->destructor = free_netdev; - /* we will validate the address ourselves in ->open */ - dev->validate_addr = NULL; -} - /* everything else */ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) -- cgit v1.2.3 From 7a725f73403e874ec52c58741e9b98cd604dbd03 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:02:00 +0200 Subject: mac80211: warn on some invalid vlan operations These should never happen, but better warn about them than crashing a driver, the fact that they never happen is rather subtle throughout mac80211. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c532043c1a1c..dd838b725afb 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -156,6 +156,9 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) if (WARN_ON(!netif_running(sdata->dev))) return 0; + if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) + return -EINVAL; + if (!local->ops->config_interface) return 0; @@ -321,6 +324,9 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; + if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) + return; + if (!changed) return; -- cgit v1.2.3 From 17741cdc264e4d768167766a252210e201c1519a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:02:02 +0200 Subject: mac80211: share STA information with driver This patch changes mac80211 to share some more data about stations with drivers. Should help iwlwifi and ath9k when they get around to updating, and might also help with implementing rate control algorithms without internals. Signed-off-by: Johannes Berg Cc: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 30 ++++++++-------- drivers/net/wireless/b43/main.c | 5 +-- drivers/net/wireless/b43legacy/main.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 12 +++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 12 +++---- drivers/net/wireless/mac80211_hwsim.c | 3 +- include/net/mac80211.h | 53 ++++++++++++++++++++++++--- net/mac80211/cfg.c | 12 +++---- net/mac80211/debugfs_key.c | 3 +- net/mac80211/debugfs_sta.c | 6 ++-- net/mac80211/ht.c | 22 ++++++------ net/mac80211/iface.c | 3 +- net/mac80211/key.c | 2 +- net/mac80211/mesh_hwmp.c | 8 ++--- net/mac80211/mesh_plink.c | 44 +++++++++++------------ net/mac80211/mlme.c | 5 +-- net/mac80211/rx.c | 12 +++---- net/mac80211/sta_info.c | 59 +++++++++++++++++++------------ net/mac80211/sta_info.h | 7 ++-- net/mac80211/tkip.c | 2 +- net/mac80211/tx.c | 10 +++--- net/mac80211/wme.c | 2 +- net/mac80211/wpa.c | 2 +- 23 files changed, 189 insertions(+), 127 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 2a6e089062f3..1ba18006f475 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1405,7 +1405,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, static void ath9k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, - const u8 *addr) + struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; struct ath_node *an; @@ -1413,19 +1413,18 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, DECLARE_MAC_BUF(mac); spin_lock_irqsave(&sc->node_lock, flags); - an = ath_node_find(sc, (u8 *) addr); + an = ath_node_find(sc, sta->addr); spin_unlock_irqrestore(&sc->node_lock, flags); switch (cmd) { case STA_NOTIFY_ADD: spin_lock_irqsave(&sc->node_lock, flags); if (!an) { - ath_node_attach(sc, (u8 *)addr, 0); + ath_node_attach(sc, sta->addr, 0); DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n", - __func__, - print_mac(mac, addr)); + __func__, print_mac(mac, sta->addr)); } else { - ath_node_get(sc, (u8 *)addr); + ath_node_get(sc, sta->addr); } spin_unlock_irqrestore(&sc->node_lock, flags); break; @@ -1438,7 +1437,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT); DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n", __func__, - print_mac(mac, addr)); + print_mac(mac, sta->addr)); } break; default: @@ -1581,45 +1580,44 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw) static int ath9k_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, - const u8 *addr, - u16 tid, - u16 *ssn) + struct ieee80211_sta *sta, + u16 tid, u16 *ssn) { struct ath_softc *sc = hw->priv; int ret = 0; switch (action) { case IEEE80211_AMPDU_RX_START: - ret = ath_rx_aggr_start(sc, addr, tid, ssn); + ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to start RX aggregation\n", __func__); break; case IEEE80211_AMPDU_RX_STOP: - ret = ath_rx_aggr_stop(sc, addr, tid); + ret = ath_rx_aggr_stop(sc, sta->addr, tid); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to stop RX aggregation\n", __func__); break; case IEEE80211_AMPDU_TX_START: - ret = ath_tx_aggr_start(sc, addr, tid, ssn); + ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to start TX aggregation\n", __func__); else - ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); + ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP: - ret = ath_tx_aggr_stop(sc, addr, tid); + ret = ath_tx_aggr_stop(sc, sta->addr, tid); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to stop TX aggregation\n", __func__); - ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); + ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); break; default: DPRINTF(sc, ATH_DBG_FATAL, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index df7a1e7f4a52..0f628a29d833 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4234,7 +4234,8 @@ out_unlock: return err; } -static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) +static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, bool set) { struct b43_wl *wl = hw_to_b43_wl(hw); unsigned long flags; @@ -4249,7 +4250,7 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) static void b43_op_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd notify_cmd, - const u8 *addr) + struct ieee80211_sta *sta) { struct b43_wl *wl = hw_to_b43_wl(hw); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 6e425410c99d..9fb1421cbec2 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3403,7 +3403,7 @@ out_unlock: } static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, - int aid, int set) + struct ieee80211_sta *sta, bool set) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); unsigned long flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 700da67ac288..af4e0b994e42 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -366,8 +366,8 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, if (state == HT_AGG_STATE_IDLE && rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", - print_mac(mac, sta->addr), tid); - ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); + print_mac(mac, sta->sta.addr), tid); + ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid); } } @@ -2244,17 +2244,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->ibss_sta_added = 0; if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, sta->addr); + u8 sta_id = iwl_find_station(priv, sta->sta.addr); DECLARE_MAC_BUF(mac); /* for IBSS the call are from tasklet */ IWL_DEBUG_RATE("LQ: ADD station %s\n", - print_mac(mac, sta->addr)); + print_mac(mac, sta->sta.addr)); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE("LQ: ADD station %s\n", - print_mac(mac, sta->addr)); - sta_id = iwl_add_station_flags(priv, sta->addr, + print_mac(mac, sta->sta.addr)); + sta_id = iwl_add_station_flags(priv, sta->sta.addr, 0, CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e8db33bf5e5d..5eeffb41d8c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3413,13 +3413,13 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn) + struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct iwl_priv *priv = hw->priv; DECLARE_MAC_BUF(mac); IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", - print_mac(mac, addr), tid); + print_mac(mac, sta->addr), tid); if (!(priv->cfg->sku & IWL_SKU_N)) return -EACCES; @@ -3427,16 +3427,16 @@ static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: IWL_DEBUG_HT("start Rx\n"); - return iwl_rx_agg_start(priv, addr, tid, *ssn); + return iwl_rx_agg_start(priv, sta->addr, tid, *ssn); case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT("stop Rx\n"); - return iwl_rx_agg_stop(priv, addr, tid); + return iwl_rx_agg_stop(priv, sta->addr, tid); case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT("start Tx\n"); - return iwl_tx_agg_start(priv, addr, tid, ssn); + return iwl_tx_agg_start(priv, sta->addr, tid, ssn); case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT("stop Tx\n"); - return iwl_tx_agg_stop(priv, addr, tid); + return iwl_tx_agg_stop(priv, sta->addr, tid); default: IWL_DEBUG_HT("unknown\n"); return -EINVAL; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index bdedf10fc86b..173dd5d2c624 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -390,7 +390,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, const u8 *addr) + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) { hwsim_check_magic(vif); } diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7f5ea55e00f5..5a6a029da4da 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -300,6 +300,9 @@ enum mac80211_tx_control_flags { * (2) driver internal use (if applicable) * (3) TX status information - driver tells mac80211 what happened * + * The TX control's sta pointer is only valid during the ->tx call, + * it may be NULL. + * * @flags: transmit info flags, defined above * @band: TBD * @tx_rate_idx: TBD @@ -329,8 +332,8 @@ struct ieee80211_tx_info { struct { struct ieee80211_vif *vif; struct ieee80211_key_conf *hw_key; + struct ieee80211_sta *sta; unsigned long jiffies; - u16 aid; s8 rts_cts_rate_idx, alt_retry_rate_idx; u8 retry_limit; u8 icv_len; @@ -651,6 +654,29 @@ enum set_key_cmd { SET_KEY, DISABLE_KEY, }; +/** + * struct ieee80211_sta - station table entry + * + * A station table entry represents a station we are possibly + * communicating with. Since stations are RCU-managed in + * mac80211, any ieee80211_sta pointer you get access to must + * either be protected by rcu_read_lock() explicitly or implicitly, + * or you must take good care to not use such a pointer after a + * call to your sta_notify callback that removed it. + * + * @addr: MAC address + * @aid: AID we assigned to the station if we're an AP + * @drv_priv: data area for driver use, will always be aligned to + * sizeof(void *), size is determined in hw information. + */ +struct ieee80211_sta { + u8 addr[ETH_ALEN]; + u16 aid; + + /* must be last */ + u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); +}; + /** * enum sta_notify_cmd - sta notify command * @@ -795,6 +821,8 @@ enum ieee80211_hw_flags { * * @vif_data_size: size (in bytes) of the drv_priv data area * within &struct ieee80211_vif. + * @sta_data_size: size (in bytes) of the drv_priv data area + * within &struct ieee80211_sta. */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -806,6 +834,7 @@ struct ieee80211_hw { unsigned int extra_tx_headroom; int channel_change_time; int vif_data_size; + int sta_data_size; u16 queues; u16 ampdu_queues; u16 max_listen_interval; @@ -1089,7 +1118,7 @@ enum ieee80211_ampdu_mlme_action { * This callback must be implemented and atomic. * * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit - * must be set or cleared for a given AID. Must be atomic. + * must be set or cleared for a given STA. Must be atomic. * * @set_key: See the section "Hardware crypto acceleration" * This callback can sleep, and is only called between add_interface @@ -1175,7 +1204,8 @@ struct ieee80211_ops { unsigned int changed_flags, unsigned int *total_flags, int mc_count, struct dev_addr_list *mc_list); - int (*set_tim)(struct ieee80211_hw *hw, int aid, int set); + int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set); int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_address, const u8 *address, struct ieee80211_key_conf *key); @@ -1192,7 +1222,7 @@ struct ieee80211_ops { int (*set_retry_limit)(struct ieee80211_hw *hw, u32 short_retry, u32 long_retr); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum sta_notify_cmd, const u8 *addr); + enum sta_notify_cmd, struct ieee80211_sta *sta); int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int (*get_tx_stats)(struct ieee80211_hw *hw, @@ -1202,7 +1232,7 @@ struct ieee80211_ops { int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn); + struct ieee80211_sta *sta, u16 tid, u16 *ssn); }; /** @@ -1752,4 +1782,17 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, */ void ieee80211_notify_mac(struct ieee80211_hw *hw, enum ieee80211_notification_types notif_type); + +/** + * ieee80211_find_sta - find a station + * + * @hw: pointer as obtained from ieee80211_alloc_hw() + * @addr: station's address + * + * This function must be called under RCU lock and the + * resulting pointer is only valid under RCU lock as well. + */ +struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, + const u8 *addr); + #endif /* MAC80211_H */ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d004351050cc..ed5e77ce627b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -364,7 +364,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, sta = sta_info_get_by_idx(local, idx, dev); if (sta) { ret = 0; - memcpy(mac, sta->addr, ETH_ALEN); + memcpy(mac, sta->sta.addr, ETH_ALEN); sta_set_sinfo(sta, sinfo); } @@ -593,7 +593,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ memset(msg->da, 0xff, ETH_ALEN); - memcpy(msg->sa, sta->addr, ETH_ALEN); + memcpy(msg->sa, sta->sta.addr, ETH_ALEN); msg->len = htons(6); msg->dsap = 0; msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ @@ -648,9 +648,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, */ if (params->aid) { - sta->aid = params->aid; - if (sta->aid > IEEE80211_MAX_AID) - sta->aid = 0; /* XXX: should this be an error? */ + sta->sta.aid = params->aid; + if (sta->sta.aid > IEEE80211_MAX_AID) + sta->sta.aid = 0; /* XXX: should this be an error? */ } if (params->listen_interval >= 0) @@ -919,7 +919,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, struct mpath_info *pinfo) { if (mpath->next_hop) - memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); + memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); else memset(next_hop, 0, ETH_ALEN); diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index cf82acec913a..a3294d109322 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -206,7 +206,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) rcu_read_lock(); sta = rcu_dereference(key->sta); if (sta) - sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr)); + sprintf(buf, "../../stations/%s", + print_mac(mac, sta->sta.addr)); rcu_read_unlock(); /* using sta as a boolean is fine outside RCU lock */ diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6abe5427752b..81f350eaf8a3 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -50,7 +50,7 @@ static const struct file_operations sta_ ##name## _ops = { \ STA_READ_##format(name, field) \ STA_OPS(name) -STA_FILE(aid, aid, D); +STA_FILE(aid, sta.aid, D); STA_FILE(dev, sdata->dev->name, S); STA_FILE(rx_packets, rx_packets, LU); STA_FILE(tx_packets, tx_packets, LU); @@ -176,7 +176,7 @@ static ssize_t sta_agg_status_write(struct file *file, struct net_device *dev = sta->sdata->dev; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; - u8 *da = sta->addr; + u8 *da = sta->sta.addr; static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1, @@ -253,7 +253,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) if (!stations_dir) return; - mac = print_mac(mbuf, sta->addr); + mac = print_mac(mbuf, sta->sta.addr); sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); if (!sta->debugfs.dir) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index bc3c71ad7ae3..dc7d9a3d70d5 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -274,7 +274,7 @@ void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *r #endif /* CONFIG_MAC80211_HT_DEBUG */ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, - ra, tid, NULL); + &sta->sta, tid, NULL); if (ret) printk(KERN_DEBUG "HW problem - can not stop rx " "aggregation for tid %d\n", tid); @@ -328,7 +328,7 @@ static void sta_addba_resp_timer_expired(unsigned long data) rcu_read_lock(); - sta = sta_info_get(local, temp_sta->addr); + sta = sta_info_get(local, temp_sta->sta.addr); if (!sta) { rcu_read_unlock(); return; @@ -354,7 +354,7 @@ static void sta_addba_resp_timer_expired(unsigned long data) /* go through the state check in stop_BA_session */ *state = HT_AGG_STATE_OPERATIONAL; spin_unlock_bh(&sta->lock); - ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, + ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid, WLAN_BACK_INITIATOR); timer_expired_exit: @@ -465,7 +465,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) if (local->ops->ampdu_action) ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, - ra, tid, &start_seq_num); + &sta->sta, tid, &start_seq_num); if (ret) { /* No need to requeue the packets in the agg queue, since we @@ -557,7 +557,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, if (local->ops->ampdu_action) ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, - ra, tid, NULL); + &sta->sta, tid, NULL); /* case HW denied going back to legacy */ if (ret) { @@ -767,7 +767,7 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); #endif - ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, (u16)*ptid, WLAN_BACK_TIMER, WLAN_REASON_QSTA_TIMEOUT); } @@ -874,7 +874,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, if (local->ops->ampdu_action) ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, - sta->addr, tid, &start_seq_num); + &sta->sta, tid, &start_seq_num); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); #endif /* CONFIG_MAC80211_HT_DEBUG */ @@ -899,7 +899,7 @@ end: spin_unlock_bh(&sta->lock); end_no_lock: - ieee80211_send_addba_resp(sta->sdata, sta->addr, tid, + ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, dialog_token, status, 1, buf_size, timeout); } @@ -952,7 +952,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, /* this will allow the state check in stop_BA_session */ *state = HT_AGG_STATE_OPERATIONAL; spin_unlock_bh(&sta->lock); - ieee80211_stop_tx_ba_session(hw, sta->addr, tid, + ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid, WLAN_BACK_INITIATOR); } } @@ -979,14 +979,14 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, #endif /* CONFIG_MAC80211_HT_DEBUG */ if (initiator == WLAN_BACK_INITIATOR) - ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid, + ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid, WLAN_BACK_INITIATOR, 0); else { /* WLAN_BACK_RECIPIENT */ spin_lock_bh(&sta->lock); sta->ampdu_mlme.tid_state_tx[tid] = HT_AGG_STATE_OPERATIONAL; spin_unlock_bh(&sta->lock); - ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, + ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid, WLAN_BACK_RECIPIENT); } } diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index f528962b13e3..a7ef0289fbdb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -336,7 +336,8 @@ static int ieee80211_stop(struct net_device *dev) list_for_each_entry_rcu(sta, &local->sta_list, list) { if (sta->sdata == sdata) - ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); + ieee80211_sta_tear_down_BA_sessions(sdata, + sta->sta.addr); } rcu_read_unlock(); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index d5b95748db2a..57afcd38cd9e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -123,7 +123,7 @@ static const u8 *get_mac_for_key(struct ieee80211_key *key) addr = zero_addr; if (key->sta) - addr = key->sta->addr; + addr = key->sta->sta.addr; return addr; } diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 1fad792ad258..15a5c99270a8 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -517,7 +517,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, spin_unlock_bh(&mpath->state_lock); goto fail; } - memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); + memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); spin_unlock_bh(&mpath->state_lock); --ttl; flags = PREP_IE_FLAGS(prep_elem); @@ -529,7 +529,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, cpu_to_le32(orig_dsn), 0, dst_addr, - cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl, + cpu_to_le32(dst_dsn), mpath->next_hop->sta.addr, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), 0, sdata); rcu_read_unlock(); @@ -557,7 +557,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_ACTIVE && - memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 && + memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && (!(mpath->flags & MESH_PATH_DSN_VALID) || DSN_GT(dst_dsn, mpath->dsn))) { mpath->flags &= ~MESH_PATH_ACTIVE; @@ -799,7 +799,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - memcpy(hdr->addr1, mpath->next_hop->addr, + memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); } else { if (!(mpath->flags & MESH_PATH_RESOLVING)) { diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 990a4b7f6bcc..debf7834dbc6 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -275,7 +275,7 @@ static void mesh_plink_timer(unsigned long data) return; } mpl_dbg("Mesh plink timer for %s fired on state %d\n", - print_mac(mac, sta->addr), sta->plink_state); + print_mac(mac, sta->sta.addr), sta->plink_state); reason = 0; llid = sta->llid; plid = sta->plid; @@ -288,7 +288,7 @@ static void mesh_plink_timer(unsigned long data) if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { u32 rand; mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n", - print_mac(mac, sta->addr), + print_mac(mac, sta->sta.addr), sta->plink_retries, sta->plink_timeout); get_random_bytes(&rand, sizeof(u32)); sta->plink_timeout = sta->plink_timeout + @@ -296,7 +296,7 @@ static void mesh_plink_timer(unsigned long data) ++sta->plink_retries; mod_plink_timer(sta, sta->plink_timeout); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, 0, 0); break; } @@ -309,7 +309,7 @@ static void mesh_plink_timer(unsigned long data) sta->plink_state = PLINK_HOLDING; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, plid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; case PLINK_HOLDING: @@ -352,10 +352,10 @@ int mesh_plink_open(struct sta_info *sta) mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); mpl_dbg("Mesh plink: starting establishment with %s\n", - print_mac(mac, sta->addr)); + print_mac(mac, sta->sta.addr)); return mesh_plink_frame_tx(sdata, PLINK_OPEN, - sta->addr, llid, 0, 0); + sta->sta.addr, llid, 0, 0); } void mesh_plink_block(struct sta_info *sta) @@ -379,7 +379,7 @@ int mesh_plink_close(struct sta_info *sta) #endif mpl_dbg("Mesh plink: closing link with %s\n", - print_mac(mac, sta->addr)); + print_mac(mac, sta->sta.addr)); spin_lock_bh(&sta->lock); sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); reason = sta->reason; @@ -400,7 +400,7 @@ int mesh_plink_close(struct sta_info *sta) llid = sta->llid; plid = sta->plid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); return 0; } @@ -577,9 +577,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->llid = llid; mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, 0, 0); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, plid, 0); break; default: @@ -604,7 +604,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: @@ -613,7 +613,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->plid = plid; llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, plid, 0); break; case CNF_ACPT: @@ -646,13 +646,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, plid, 0); break; case CNF_ACPT: @@ -661,7 +661,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mesh_plink_inc_estab_count(sdata); spin_unlock_bh(&sta->lock); mpl_dbg("Mesh plink with %s ESTABLISHED\n", - print_mac(mac, sta->addr)); + print_mac(mac, sta->sta.addr)); break; default: spin_unlock_bh(&sta->lock); @@ -685,7 +685,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: @@ -694,8 +694,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mesh_plink_inc_estab_count(sdata); spin_unlock_bh(&sta->lock); mpl_dbg("Mesh plink with %s ESTABLISHED\n", - print_mac(mac, sta->addr)); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, + print_mac(mac, sta->sta.addr)); + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, plid, 0); break; default: @@ -714,13 +714,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, reason); break; case OPN_ACPT: llid = sta->llid; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->addr, llid, + mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, plid, 0); break; default: @@ -743,8 +743,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m llid = sta->llid; reason = sta->reason; spin_unlock_bh(&sta->lock); - mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->addr, llid, - plid, reason); + mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, + llid, plid, reason); break; default: spin_unlock_bh(&sta->lock); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8a2cfd3609b5..35c421b89dd2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -804,7 +804,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, netif_tx_stop_all_queues(sdata->dev); netif_carrier_off(sdata->dev); - ieee80211_sta_tear_down_BA_sessions(sdata, sta->addr); + ieee80211_sta_tear_down_BA_sessions(sdata, sta->sta.addr); if (self_disconnected) { if (deauth) @@ -1507,7 +1507,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: updated supp_rates set " "for %s based on beacon info (0x%llx | " "0x%llx -> 0x%llx)\n", - sdata->dev->name, print_mac(mac, sta->addr), + sdata->dev->name, + print_mac(mac, sta->sta.addr), (unsigned long long) prev_rates, (unsigned long long) supp_rates, (unsigned long long) sta->supp_rates[band]); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8c3dda5f00b2..92d898b901e9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -661,7 +661,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", - dev->name, print_mac(mac, sta->addr), sta->aid); + dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } @@ -685,7 +685,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", - dev->name, print_mac(mac, sta->addr), sta->aid); + dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ @@ -702,7 +702,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " "since STA not sleeping anymore\n", dev->name, - print_mac(mac, sta->addr), sta->aid); + print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ info->flags |= IEEE80211_TX_CTL_REQUEUE; dev_queue_xmit(skb); @@ -1007,7 +1007,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", - print_mac(mac, rx->sta->addr), rx->sta->aid, + print_mac(mac, rx->sta->sta.addr), rx->sta->sta.aid, skb_queue_len(&rx->sta->ps_tx_buf)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ @@ -1032,7 +1032,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) */ printk(KERN_DEBUG "%s: STA %s sent PS Poll even " "though there are no buffered frames for it\n", - rx->dev->name, print_mac(mac, rx->sta->addr)); + rx->dev->name, print_mac(mac, rx->sta->sta.addr)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } @@ -2140,7 +2140,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, /* if this mpdu is fragmented - terminate rx aggregation session */ sc = le16_to_cpu(hdr->seq_ctrl); if (sc & IEEE80211_SCTL_FRAG) { - ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); ret = 1; goto end_reorder; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 31246d8e5327..d9774ac2e0f7 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -73,11 +73,11 @@ static int sta_info_hash_del(struct ieee80211_local *local, { struct sta_info *s; - s = local->sta_hash[STA_HASH(sta->addr)]; + s = local->sta_hash[STA_HASH(sta->sta.addr)]; if (!s) return -ENOENT; if (s == sta) { - rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], + rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], s->hnext); return 0; } @@ -94,13 +94,13 @@ static int sta_info_hash_del(struct ieee80211_local *local, /* protected by RCU */ static struct sta_info *__sta_info_find(struct ieee80211_local *local, - u8 *addr) + const u8 *addr) { struct sta_info *sta; sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); while (sta) { - if (compare_ether_addr(sta->addr, addr) == 0) + if (compare_ether_addr(sta->sta.addr, addr) == 0) break; sta = rcu_dereference(sta->hnext); } @@ -151,7 +151,7 @@ static void __sta_info_free(struct ieee80211_local *local, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Destroyed STA %s\n", - wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); + wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ kfree(sta); @@ -219,8 +219,8 @@ void sta_info_destroy(struct sta_info *sta) static void sta_info_hash_add(struct ieee80211_local *local, struct sta_info *sta) { - sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; - rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta); + sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; + rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); } struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, @@ -231,14 +231,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, int i; DECLARE_MAC_BUF(mbuf); - sta = kzalloc(sizeof(*sta), gfp); + sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); if (!sta) return NULL; spin_lock_init(&sta->lock); spin_lock_init(&sta->flaglock); - memcpy(sta->addr, addr, ETH_ALEN); + memcpy(sta->sta.addr, addr, ETH_ALEN); sta->local = local; sta->sdata = sdata; @@ -271,7 +271,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Allocated STA %s\n", - wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); + wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ #ifdef CONFIG_MAC80211_MESH @@ -300,15 +300,15 @@ int sta_info_insert(struct sta_info *sta) goto out_free; } - if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 || - is_multicast_ether_addr(sta->addr))) { + if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || + is_multicast_ether_addr(sta->sta.addr))) { err = -EINVAL; goto out_free; } spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (__sta_info_find(local, sta->addr)) { + if (__sta_info_find(local, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); err = -EEXIST; goto out_free; @@ -325,12 +325,12 @@ int sta_info_insert(struct sta_info *sta) u.ap); local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_ADD, sta->addr); + STA_NOTIFY_ADD, &sta->sta); } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Inserted STA %s\n", - wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); + wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr)); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ spin_unlock_irqrestore(&local->sta_lock, flags); @@ -379,11 +379,12 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, { BUG_ON(!bss); - __bss_tim_set(bss, sta->aid); + __bss_tim_set(bss, sta->sta.aid); if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; - sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); + sta->local->ops->set_tim(local_to_hw(sta->local), + &sta->sta, true); sta->local->tim_in_locked_section = false; } } @@ -404,11 +405,12 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, { BUG_ON(!bss); - __bss_tim_clear(bss, sta->aid); + __bss_tim_clear(bss, sta->sta.aid); if (sta->local->ops->set_tim) { sta->local->tim_in_locked_section = true; - sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); + sta->local->ops->set_tim(local_to_hw(sta->local), + &sta->sta, false); sta->local->tim_in_locked_section = false; } } @@ -462,7 +464,7 @@ static void __sta_info_unlink(struct sta_info **sta) u.ap); local->ops->sta_notify(local_to_hw(local), &sdata->vif, - STA_NOTIFY_REMOVE, (*sta)->addr); + STA_NOTIFY_REMOVE, &(*sta)->sta); } if (ieee80211_vif_is_mesh(&sdata->vif)) { @@ -474,7 +476,7 @@ static void __sta_info_unlink(struct sta_info **sta) #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Removed STA %s\n", - wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr)); + wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr)); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ /* @@ -570,7 +572,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, local->total_ps_buffered--; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "Buffered frame expired (STA " - "%s)\n", print_mac(mac, sta->addr)); + "%s)\n", print_mac(mac, sta->sta.addr)); #endif dev_kfree_skb(skb); @@ -817,7 +819,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %s\n", - sdata->dev->name, print_mac(mac, sta->addr)); + sdata->dev->name, print_mac(mac, sta->sta.addr)); #endif __sta_info_unlink(&sta); if (sta) @@ -828,3 +830,14 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, list_for_each_entry_safe(sta, tmp, &tmp_list, list) sta_info_destroy(sta); } + +struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, + const u8 *addr) +{ + struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); + + if (!sta) + return NULL; + return &sta->sta; +} +EXPORT_SYMBOL(ieee80211_find_sta); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 220079900991..e7ce12dbf270 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -218,6 +218,7 @@ struct sta_ampdu_mlme { * @plink_timeout: TBD * @plink_timer: TBD * @debugfs: debug filesystem info + * @sta: station information we share with the driver */ struct sta_info { /* General information, mostly static */ @@ -232,8 +233,7 @@ struct sta_info { spinlock_t flaglock; struct ieee80211_ht_info ht_info; u64 supp_rates[IEEE80211_NUM_BANDS]; - u8 addr[ETH_ALEN]; - u16 aid; + u16 listen_interval; /* @@ -327,6 +327,9 @@ struct sta_info { struct dentry *agg_status; } debugfs; #endif + + /* keep last! */ + struct ieee80211_sta sta; }; static inline enum plink_state sta_plink_state(struct sta_info *sta) diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 995f7af3d25e..34b32bc8f609 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -304,7 +304,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 *sta_addr = key->sta->addr; + u8 *sta_addr = key->sta->sta.addr; if (is_multicast_ether_addr(ra)) sta_addr = bcast; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f4bcc589d674..07bf228d0b16 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -381,7 +381,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " "before %d)\n", - print_mac(mac, sta->addr), sta->aid, + print_mac(mac, sta->sta.addr), sta->sta.aid, skb_queue_len(&sta->ps_tx_buf)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) @@ -392,7 +392,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) if (net_ratelimit()) { printk(KERN_DEBUG "%s: STA %s TX " "buffer full - dropping oldest frame\n", - tx->dev->name, print_mac(mac, sta->addr)); + tx->dev->name, print_mac(mac, sta->sta.addr)); } #endif dev_kfree_skb(old); @@ -411,7 +411,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " "set -> send frame\n", tx->dev->name, - print_mac(mac, sta->addr)); + print_mac(mac, sta->sta.addr)); } #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ clear_sta_flags(sta, WLAN_STA_PSPOLL); @@ -528,7 +528,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) sband = tx->local->hw.wiphy->bands[tx->channel->band]; if (tx->sta) - info->control.aid = tx->sta->aid; + info->control.sta = &tx->sta->sta; if (!info->control.retry_limit) { if (!is_multicast_ether_addr(hdr->addr1)) { @@ -608,7 +608,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) } if (tx->sta) - info->control.aid = tx->sta->aid; + info->control.sta = &tx->sta->sta; return TX_CONTINUE; } diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 7229e958879d..6748dedcab50 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -210,7 +210,7 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "allocated aggregation queue" " %d tid %d addr %s pool=0x%lX\n", - i, tid, print_mac(mac, sta->addr), + i, tid, print_mac(mac, sta->sta.addr), local->queue_pool[0]); } #endif /* CONFIG_MAC80211_HT_DEBUG */ diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 78021780b885..37ae9a959f63 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -256,7 +256,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, key, skb->data + hdrlen, - skb->len - hdrlen, rx->sta->addr, + skb->len - hdrlen, rx->sta->sta.addr, hdr->addr1, hwaccel, rx->queue, &rx->tkip_iv32, &rx->tkip_iv16); -- cgit v1.2.3 From 95dac040041723d0c0ab245642c1b9802f12cc8d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 02:03:28 +0200 Subject: mac80211: small rate control changes This patch fixes mac80211 to not rely on the rate control algorithm to update sta->tx_retry_failed and sta->tx_retry_count (even if we don't currently use them), removes a number of completely unused values we don't even show in debugfs and changes the code in ieee80211_tx_status() to not look up the sta_info repeatedly. The only behaviour change here would be not calling the rate control function rate_control_tx_status() when no sta_info is found, but all rate control algorithms ignore such calls anyway. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 50 ++++++++++++++++++++--------------------- net/mac80211/rc80211_pid_algo.c | 11 --------- net/mac80211/sta_info.h | 7 ------ 3 files changed, 25 insertions(+), 43 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dd838b725afb..c307dba7ec03 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -546,29 +546,27 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rcu_read_lock(); - if (info->status.excessive_retries) { - sta = sta_info_get(local, hdr->addr1); - if (sta) { - if (test_sta_flags(sta, WLAN_STA_PS)) { - /* - * The STA is in power save mode, so assume - * that this TX packet failed because of that. - */ - ieee80211_handle_filtered_frame(local, sta, skb); - rcu_read_unlock(); - return; - } + sta = sta_info_get(local, hdr->addr1); + + if (sta) { + if (info->status.excessive_retries && + test_sta_flags(sta, WLAN_STA_PS)) { + /* + * The STA is in power save mode, so assume + * that this TX packet failed because of that. + */ + ieee80211_handle_filtered_frame(local, sta, skb); + rcu_read_unlock(); + return; } - } - fc = hdr->frame_control; + fc = hdr->frame_control; + + if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && + (ieee80211_is_data_qos(fc))) { + u16 tid, ssn; + u8 *qc; - if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && - (ieee80211_is_data_qos(fc))) { - u16 tid, ssn; - u8 *qc; - sta = sta_info_get(local, hdr->addr1); - if (sta) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) @@ -576,17 +574,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) ieee80211_send_bar(sta->sdata, hdr->addr1, tid, ssn); } - } - if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - sta = sta_info_get(local, hdr->addr1); - if (sta) { + if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { ieee80211_handle_filtered_frame(local, sta, skb); rcu_read_unlock(); return; + } else { + if (info->status.excessive_retries) + sta->tx_retry_failed++; + sta->tx_retry_count += info->status.retry_count; } - } else + rate_control_tx_status(local->mdev, skb); + } rcu_read_unlock(); diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 21e1942ea975..94867860c3e0 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -282,17 +282,6 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, spinfo->tx_num_xmit++; } - if (info->status.excessive_retries) { - sta->tx_retry_failed++; - sta->tx_num_consecutive_failures++; - sta->tx_num_mpdu_fail++; - } else { - sta->tx_num_consecutive_failures = 0; - sta->tx_num_mpdu_ok++; - } - sta->tx_retry_count += info->status.retry_count; - sta->tx_num_mpdu_fail += info->status.retry_count; - /* Update PID controller state. */ period = (HZ * pinfo->sampling_period + 500) / 1000; if (!period) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index e7ce12dbf270..4a9b96eeb687 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -195,9 +195,6 @@ struct sta_ampdu_mlme { * @tx_filtered_count: TBD * @tx_retry_failed: TBD * @tx_retry_count: TBD - * @tx_num_consecutive_failures: TBD - * @tx_num_mpdu_ok: TBD - * @tx_num_mpdu_fail: TBD * @fail_avg: moving percentage of failed MSDUs * @tx_packets: number of RX/TX MSDUs * @tx_bytes: TBD @@ -273,10 +270,6 @@ struct sta_info { /* Updated from TX status path only, no locking requirements */ unsigned long tx_filtered_count; unsigned long tx_retry_failed, tx_retry_count; - /* TODO: update in generic code not rate control? */ - u32 tx_num_consecutive_failures; - u32 tx_num_mpdu_ok; - u32 tx_num_mpdu_fail; /* moving percentage of failed MSDUs */ unsigned int fail_avg; -- cgit v1.2.3 From b7e35008815a1c39123f4dd53b430788e2e18da4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 02:22:58 +0200 Subject: mac80211: move last_txrate_idx into RC algorithms This variable in sta_info is only used in a meaningful way by the Intel RC algorithms, so move it into those. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 20 ++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 15 +++++++++------ net/mac80211/rc80211_pid_algo.c | 2 -- net/mac80211/sta_info.h | 2 -- 4 files changed, 21 insertions(+), 18 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index da23c927380f..46b672c34585 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -65,6 +65,9 @@ struct iwl3945_rs_sta { u8 ibss_sta_added; struct timer_list rate_scale_flush; struct iwl3945_rate_scale_data win[IWL_RATE_COUNT]; + + /* used to be in sta_info */ + int last_txrate_idx; }; static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = { @@ -319,6 +322,7 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, static void rs_rate_init(void *priv_rate, void *priv_sta, struct ieee80211_local *local, struct sta_info *sta) { + struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv; int i; IWL_DEBUG_RATE("enter\n"); @@ -335,11 +339,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, } } - sta->last_txrate_idx = sta->txrate_idx; + rs_sta->last_txrate_idx = sta->txrate_idx; /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) - sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; + rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE("leave\n"); } @@ -674,14 +678,14 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, return; } + rs_sta = (void *)sta->rate_ctrl_priv; + rate_mask = sta->supp_rates[sband->band]; - index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); + index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; - rs_sta = (void *)sta->rate_ctrl_priv; - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !rs_sta->ibss_sta_added) { u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1); @@ -803,11 +807,11 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, out: - sta->last_txrate_idx = index; + rs_sta->last_txrate_idx = index; if (sband->band == IEEE80211_BAND_5GHZ) - sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; + sta->txrate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; else - sta->txrate_idx = sta->last_txrate_idx; + sta->txrate_idx = rs_sta->last_txrate_idx; rcu_read_unlock(); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index af4e0b994e42..54f076bb2022 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -163,6 +163,9 @@ struct iwl_lq_sta { u32 dbg_fixed_rate; #endif struct iwl_priv *drv; + + /* used to be in sta_info */ + int last_txrate_idx; }; static void rs_rate_scale_perform(struct iwl_priv *priv, @@ -1746,7 +1749,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, is_green = lq_sta->is_green; /* current tx rate */ - index = sta->last_txrate_idx; + index = lq_sta->last_txrate_idx; IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, tbl->lq_type); @@ -2059,7 +2062,7 @@ lq_update: out: tbl->current_rate = rate_n_flags_from_tbl(tbl, index, is_green); i = index; - sta->last_txrate_idx = i; + lq_sta->last_txrate_idx = i; /* sta->txrate_idx is an index to A mode rates which start * at IWL_FIRST_OFDM_RATE @@ -2090,7 +2093,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, goto out; lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate_idx; + i = lq_sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) @@ -2161,7 +2164,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, } lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate_idx; + i = lq_sta->last_txrate_idx; if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) { @@ -2270,10 +2273,10 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, if (sta->supp_rates[sband->band] & BIT(i)) sta->txrate_idx = i; - sta->last_txrate_idx = sta->txrate_idx; + lq_sta->last_txrate_idx = sta->txrate_idx; /* For MODE_IEEE80211A, skip over cck rates in global rate table */ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) - sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; + lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_dup = 0; lq_sta->is_green = rs_use_green(priv, conf); diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 94867860c3e0..24e44f521302 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -329,8 +329,6 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, if (rateidx >= sband->n_bitrates) rateidx = sband->n_bitrates - 1; - sta->last_txrate_idx = rateidx; - rcu_read_unlock(); sel->rate_idx = rateidx; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4a9b96eeb687..df42d1815458 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -200,7 +200,6 @@ struct sta_ampdu_mlme { * @tx_bytes: TBD * @tx_fragments: number of transmitted MPDUs * @txrate_idx: TBD - * @last_txrate_idx: TBD * @tid_seq: TBD * @wme_tx_queue: TBD * @ampdu_mlme: TBD @@ -278,7 +277,6 @@ struct sta_info { unsigned long tx_bytes; unsigned long tx_fragments; int txrate_idx; - int last_txrate_idx; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; #ifdef CONFIG_MAC80211_DEBUG_COUNTERS unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; -- cgit v1.2.3 From 323ce79a9cdbf838ea577677b1ddace8e0b4d4c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 02:45:11 +0200 Subject: mac80211: share sta->supp_rates As more preparation for a saner rate control algorithm API, share the supported rates bitmap in the public API. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 6 +++--- include/net/mac80211.h | 2 ++ net/mac80211/cfg.c | 2 +- net/mac80211/mesh_plink.c | 4 ++-- net/mac80211/mlme.c | 12 ++++++------ net/mac80211/rate.h | 2 +- net/mac80211/sta_info.h | 2 -- 9 files changed, 18 insertions(+), 18 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 390019ed398e..226d70c73fe6 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1825,7 +1825,7 @@ static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; for (i = 0; i < sband->n_bitrates; i++) { - if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) { + if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) { rc_priv->neg_rates.rs_rates[j] = (sband->bitrates[i].bitrate * 2) / 10; j++; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 46b672c34585..f751b9097592 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -333,7 +333,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { - if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) { + if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) { sta->txrate_idx = i; break; } @@ -680,7 +680,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, rs_sta = (void *)sta->rate_ctrl_priv; - rate_mask = sta->supp_rates[sband->band]; + rate_mask = sta->sta.supp_rates[sband->band]; index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 54f076bb2022..f7191a9a7fb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1731,7 +1731,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, return; lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; - lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; + lq_sta->supp_rates = sta->sta.supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); @@ -2233,7 +2233,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; lq_sta->flush_timer = 0; - lq_sta->supp_rates = sta->supp_rates[sband->band]; + lq_sta->supp_rates = sta->sta.supp_rates[sband->band]; sta->txrate_idx = 3; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) @@ -2270,7 +2270,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* Find highest tx rate supported by hardware and destination station */ for (i = 0; i < sband->n_bitrates; i++) - if (sta->supp_rates[sband->band] & BIT(i)) + if (sta->sta.supp_rates[sband->band] & BIT(i)) sta->txrate_idx = i; lq_sta->last_txrate_idx = sta->txrate_idx; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5a6a029da4da..ef8e4cc32c2e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -666,10 +666,12 @@ enum set_key_cmd { * * @addr: MAC address * @aid: AID we assigned to the station if we're an AP + * @supp_rates: Bitmap of supported rates (per band) * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *), size is determined in hw information. */ struct ieee80211_sta { + u64 supp_rates[IEEE80211_NUM_BANDS]; u8 addr[ETH_ALEN]; u16 aid; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ed5e77ce627b..47988d2eb15c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -667,7 +667,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, rates |= BIT(j); } } - sta->supp_rates[local->oper_channel->band] = rates; + sta->sta.supp_rates[local->oper_channel->band] = rates; } if (params->ht_capa) { diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index debf7834dbc6..faac101c0f85 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -106,7 +106,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, return NULL; sta->flags = WLAN_STA_AUTHORIZED; - sta->supp_rates[local->hw.conf.channel->band] = rates; + sta->sta.supp_rates[local->hw.conf.channel->band] = rates; return sta; } @@ -243,7 +243,7 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data } sta->last_rx = jiffies; - sta->supp_rates[local->hw.conf.channel->band] = rates; + sta->sta.supp_rates[local->hw.conf.channel->band] = rates; if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && sdata->u.mesh.accepting_plinks && sdata->u.mesh.mshcfg.auto_open_plinks) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 35c421b89dd2..c049f336e58a 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1301,7 +1301,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, } } - sta->supp_rates[local->hw.conf.channel->band] = rates; + sta->sta.supp_rates[local->hw.conf.channel->band] = rates; sdata->bss_conf.basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ @@ -1497,13 +1497,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (sta) { u64 prev_rates; - prev_rates = sta->supp_rates[band]; + prev_rates = sta->sta.supp_rates[band]; /* make sure mandatory rates are always added */ - sta->supp_rates[band] = supp_rates | + sta->sta.supp_rates[band] = supp_rates | ieee80211_mandatory_rates(local, band); #ifdef CONFIG_MAC80211_IBSS_DEBUG - if (sta->supp_rates[band] != prev_rates) + if (sta->sta.supp_rates[band] != prev_rates) printk(KERN_DEBUG "%s: updated supp_rates set " "for %s based on beacon info (0x%llx | " "0x%llx -> 0x%llx)\n", @@ -1511,7 +1511,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, print_mac(mac, sta->sta.addr), (unsigned long long) prev_rates, (unsigned long long) supp_rates, - (unsigned long long) sta->supp_rates[band]); + (unsigned long long) sta->sta.supp_rates[band]); #endif } else { ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, @@ -2339,7 +2339,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, set_sta_flags(sta, WLAN_STA_AUTHORIZED); /* make sure mandatory rates are always added */ - sta->supp_rates[band] = supp_rates | + sta->sta.supp_rates[band] = supp_rates | ieee80211_mandatory_rates(local, band); rate_control_rate_init(sta, local); diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index ede7ab56f65b..5f18c27eb900 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -134,7 +134,7 @@ static inline int rate_supported(struct sta_info *sta, enum ieee80211_band band, int index) { - return (sta == NULL || sta->supp_rates[band] & BIT(index)); + return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); } static inline s8 diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index df42d1815458..4dafa044b2f2 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -168,7 +168,6 @@ struct sta_ampdu_mlme { * in the header file. * @flaglock: spinlock for flags accesses * @ht_info: HT capabilities of this STA - * @supp_rates: Bitmap of supported rates (per band) * @addr: MAC address of this STA * @aid: STA's unique AID (1..2007, 0 = not assigned yet), * only used in AP (and IBSS?) mode @@ -228,7 +227,6 @@ struct sta_info { spinlock_t lock; spinlock_t flaglock; struct ieee80211_ht_info ht_info; - u64 supp_rates[IEEE80211_NUM_BANDS]; u16 listen_interval; -- cgit v1.2.3 From ae17e986091637e7ef5a8224c7b689029b105131 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 03:04:36 +0200 Subject: mac80211: move txrate_idx into RC algorithms The sta_info->txrate_idx member isn't used by all RC algorithms in the way it was intended to be used, move it into those that require it (only PID) and keep track in the core code of which rate was last used for reporting to userspace and the mesh MLME. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 10 +++------ drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 13 ++---------- net/mac80211/mesh_hwmp.c | 2 +- net/mac80211/rc80211_pid.h | 2 ++ net/mac80211/rc80211_pid_algo.c | 33 +++++++++++++++++------------- net/mac80211/sta_info.h | 2 +- net/mac80211/tx.c | 2 ++ net/mac80211/wext.c | 4 ++-- 9 files changed, 32 insertions(+), 37 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 226d70c73fe6..1cc9daf44550 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -2039,7 +2039,6 @@ static void ath_rate_init(void *priv, void *priv_sta, DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - sta->txrate_idx = rate_lowest_index(local, sband, sta); ath_setup_rates(local, sta); if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index f751b9097592..a279bf1dc9b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -334,13 +334,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) { - sta->txrate_idx = i; + rs_sta->last_txrate_idx = i; break; } } - rs_sta->last_txrate_idx = sta->txrate_idx; - /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; @@ -809,15 +807,13 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, rs_sta->last_txrate_idx = index; if (sband->band == IEEE80211_BAND_5GHZ) - sta->txrate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; + sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; else - sta->txrate_idx = rs_sta->last_txrate_idx; + sel->rate_idx = rs_sta->last_txrate_idx; rcu_read_unlock(); IWL_DEBUG_RATE("leave: %d\n", index); - - sel->rate_idx = sta->txrate_idx; } static struct rate_control_ops rs_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f7191a9a7fb7..a8711c314e6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2064,14 +2064,6 @@ out: i = index; lq_sta->last_txrate_idx = i; - /* sta->txrate_idx is an index to A mode rates which start - * at IWL_FIRST_OFDM_RATE - */ - if (lq_sta->band == IEEE80211_BAND_5GHZ) - sta->txrate_idx = i - IWL_FIRST_OFDM_RATE; - else - sta->txrate_idx = i; - return; } @@ -2234,7 +2226,6 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->flush_timer = 0; lq_sta->supp_rates = sta->sta.supp_rates[sband->band]; - sta->txrate_idx = 3; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); @@ -2269,11 +2260,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, } /* Find highest tx rate supported by hardware and destination station */ + lq_sta->last_txrate_idx = 3; for (i = 0; i < sband->n_bitrates; i++) if (sta->sta.supp_rates[sband->band] & BIT(i)) - sta->txrate_idx = i; + lq_sta->last_txrate_idx = i; - lq_sta->last_txrate_idx = sta->txrate_idx; /* For MODE_IEEE80211A, skip over cck rates in global rate table */ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 15a5c99270a8..501c7831adb4 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -223,7 +223,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, /* bitrate is in units of 100 Kbps, while we need rate in units of * 1Mbps. This will be corrected on tx_time computation. */ - rate = sband->bitrates[sta->txrate_idx].bitrate; + rate = sband->bitrates[sta->last_txrate_idx].bitrate; tx_time = (device_constant + 10 * test_frame_len / rate); estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 0a9135b974b5..ffafc5da572e 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h @@ -180,6 +180,8 @@ struct rc_pid_sta_info { u32 tx_num_failed; u32 tx_num_xmit; + int txrate_idx; + /* Average failed frames percentage error (i.e. actual vs. target * percentage), scaled by RC_PID_SMOOTHING. This value is computed * using using an exponential weighted average technique: diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 24e44f521302..bc1c4569caa1 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -75,7 +75,8 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata; struct ieee80211_supported_band *sband; int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; - int cur = sta->txrate_idx; + struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; + int cur = spinfo->txrate_idx; sdata = sta->sdata; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; @@ -111,7 +112,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, /* Fit the rate found to the nearest supported rate. */ do { if (rate_supported(sta, band, rinfo[tmp].index)) { - sta->txrate_idx = rinfo[tmp].index; + spinfo->txrate_idx = rinfo[tmp].index; break; } if (adj < 0) @@ -121,9 +122,9 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, } while (tmp < n_bitrates && tmp >= 0); #ifdef CONFIG_MAC80211_DEBUGFS - rate_control_pid_event_rate_change( - &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, - sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate); + rate_control_pid_event_rate_change(&spinfo->events, + spinfo->txrate_idx, + sband->bitrates[spinfo->txrate_idx].bitrate); #endif } @@ -190,16 +191,16 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, spinfo->tx_num_failed = 0; /* If we just switched rate, update the rate behaviour info. */ - if (pinfo->oldrate != sta->txrate_idx) { + if (pinfo->oldrate != spinfo->txrate_idx) { i = rinfo[pinfo->oldrate].rev_index; - j = rinfo[sta->txrate_idx].rev_index; + j = rinfo[spinfo->txrate_idx].rev_index; tmp = (pf - spinfo->last_pf); tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); rinfo[j].diff = rinfo[i].diff + tmp; - pinfo->oldrate = sta->txrate_idx; + pinfo->oldrate = spinfo->txrate_idx; } rate_control_pid_normalize(pinfo, sband->n_bitrates); @@ -252,19 +253,20 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, if (!sta) goto unlock; + spinfo = sta->rate_ctrl_priv; + /* Don't update the state if we're not controlling the rate. */ sdata = sta->sdata; if (sdata->force_unicast_rateidx > -1) { - sta->txrate_idx = sdata->max_ratectrl_rateidx; + spinfo->txrate_idx = sdata->max_ratectrl_rateidx; goto unlock; } /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ - if (info->tx_rate_idx != sta->txrate_idx) + if (info->tx_rate_idx != spinfo->txrate_idx) goto unlock; - spinfo = sta->rate_ctrl_priv; spinfo->tx_num_xmit++; #ifdef CONFIG_MAC80211_DEBUGFS @@ -301,6 +303,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_sub_if_data *sdata; + struct rc_pid_sta_info *spinfo; struct sta_info *sta; int rateidx; u16 fc; @@ -321,10 +324,11 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, /* If a forced rate is in effect, select it. */ sdata = IEEE80211_DEV_TO_SUB_IF(dev); + spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; if (sdata->force_unicast_rateidx > -1) - sta->txrate_idx = sdata->force_unicast_rateidx; + spinfo->txrate_idx = sdata->force_unicast_rateidx; - rateidx = sta->txrate_idx; + rateidx = spinfo->txrate_idx; if (rateidx >= sband->n_bitrates) rateidx = sband->n_bitrates - 1; @@ -349,9 +353,10 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta, * Until that method is implemented, we will use the lowest supported * rate as a workaround. */ struct ieee80211_supported_band *sband; + struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - sta->txrate_idx = rate_lowest_index(local, sband, sta); + spinfo->txrate_idx = rate_lowest_index(local, sband, sta); sta->fail_avg = 0; } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4dafa044b2f2..5d8fabf7a68b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -274,7 +274,7 @@ struct sta_info { unsigned long tx_packets; unsigned long tx_bytes; unsigned long tx_fragments; - int txrate_idx; + unsigned int last_txrate_idx; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; #ifdef CONFIG_MAC80211_DEBUG_COUNTERS unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 07bf228d0b16..7468495d6f9c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -485,6 +485,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) if (likely(tx->rate_idx < 0)) { rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); + if (tx->sta) + tx->sta->last_txrate_idx = rsel.rate_idx; tx->rate_idx = rsel.rate_idx; if (unlikely(rsel.probe_idx >= 0)) { info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index aef9707700fd..7e0d53abde24 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -636,8 +636,8 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, sta = sta_info_get(local, sdata->u.sta.bssid); - if (sta && sta->txrate_idx < sband->n_bitrates) - rate->value = sband->bitrates[sta->txrate_idx].bitrate; + if (sta && sta->last_txrate_idx < sband->n_bitrates) + rate->value = sband->bitrates[sta->last_txrate_idx].bitrate; else rate->value = 0; -- cgit v1.2.3 From 687c7c0807371aeaa94ff2fff511eeb326b5c5de Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 03:14:11 +0200 Subject: mac80211: share sta_info->ht_info Rate control algorithms may need access to a station's HT capabilities, so share the ht_info struct in the public station API. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 6 +++--- include/net/mac80211.h | 2 ++ net/mac80211/cfg.c | 2 +- net/mac80211/mlme.c | 4 ++-- net/mac80211/sta_info.h | 2 -- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a8711c314e6a..f45a752e93c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1154,10 +1154,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, s8 is_green = lq_sta->is_green; if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || - !sta->ht_info.ht_supported) + !sta->sta.ht_info.ht_supported) return -1; - if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + if (((sta->sta.ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) == WLAN_HT_CAP_SM_PS_STATIC) return -1; @@ -1222,7 +1222,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, s32 rate; if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || - !sta->ht_info.ht_supported) + !sta->sta.ht_info.ht_supported) return -1; IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ef8e4cc32c2e..d6669fd3ffa8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -667,6 +667,7 @@ enum set_key_cmd { * @addr: MAC address * @aid: AID we assigned to the station if we're an AP * @supp_rates: Bitmap of supported rates (per band) + * @ht_info: HT capabilities of this STA * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *), size is determined in hw information. */ @@ -674,6 +675,7 @@ struct ieee80211_sta { u64 supp_rates[IEEE80211_NUM_BANDS]; u8 addr[ETH_ALEN]; u16 aid; + struct ieee80211_ht_info ht_info; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 47988d2eb15c..e2574885db4a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -672,7 +672,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, if (params->ht_capa) { ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, - &sta->ht_info); + &sta->sta.ht_info); } if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c049f336e58a..8611a8318c9c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1316,11 +1316,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_ht_bss_info bss_info; ieee80211_ht_cap_ie_to_ht_info( (struct ieee80211_ht_cap *) - elems.ht_cap_elem, &sta->ht_info); + elems.ht_cap_elem, &sta->sta.ht_info); ieee80211_ht_addt_info_ie_to_ht_bss_info( (struct ieee80211_ht_addt_info *) elems.ht_info_elem, &bss_info); - ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info); + ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); } rate_control_rate_init(sta, local); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5d8fabf7a68b..b773c7b8d296 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -167,7 +167,6 @@ struct sta_ampdu_mlme { * @lock: used for locking all fields that require locking, see comments * in the header file. * @flaglock: spinlock for flags accesses - * @ht_info: HT capabilities of this STA * @addr: MAC address of this STA * @aid: STA's unique AID (1..2007, 0 = not assigned yet), * only used in AP (and IBSS?) mode @@ -226,7 +225,6 @@ struct sta_info { void *rate_ctrl_priv; spinlock_t lock; spinlock_t flaglock; - struct ieee80211_ht_info ht_info; u16 listen_interval; -- cgit v1.2.3 From 3061307013267c2c75efae3925f461858d832101 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 05:27:40 +0200 Subject: mac80211: pass AP vif pointer for VLANs We cannot pass a VLAN vif pointer to the driver since those are entirely virtual and we never tell the driver. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7468495d6f9c..698c8233e6b3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1351,6 +1351,10 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, return 0; } + if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) + osdata = container_of(osdata->bss, + struct ieee80211_sub_if_data, + u.ap); info->control.vif = &osdata->vif; ret = ieee80211_tx(odev, skb); dev_put(odev); -- cgit v1.2.3 From 25d834e16294c8dfd923dae6bdb8a055391a99a5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Sep 2008 22:52:47 +0200 Subject: mac80211: fix virtual interfaces vs. injection Currently, virtual interface pointers passed to drivers might be from monitor interfaces and as such completely uninitialised because we do not tell the driver about monitor interfaces when those are created. Instead of passing them, we should therefore indicate to the driver that there is no information; do that by passing a NULL value and adjust drivers to cope with it. As a result, some mac80211 API functions also need to cope with a NULL vif pointer so drivers can still call them unconditionally. Also, when injecting frames we really don't want to pass NULL all the time, if we know we are the source address of a frame and have a local interface for that address, we can to use that interface. This also helps with processing the frame correctly for that interface which will help the 802.11w implementation. It's not entirely correct for VLANs or WDS interfaces because there the MAC address isn't unique, but it's already a lot better than what we do now. Finally, when injecting without a matching local interface, don't assign sequence numbers at all. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 3 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 21 ++++++---- include/net/mac80211.h | 1 + net/mac80211/tx.c | 64 +++++++++++++++++++++++++++++-- net/mac80211/util.c | 37 ++++++++++++------ 5 files changed, 101 insertions(+), 25 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index da8aa83481f7..631d65b73edf 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -258,7 +258,8 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) txi = IEEE80211_SKB_CB(skb); - hwsim_check_magic(txi->control.vif); + if (txi->control.vif) + hwsim_check_magic(txi->control.vif); if (txi->control.sta) hwsim_check_sta_magic(txi->control.sta); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a5e965068c83..b7f4fe8fba6e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -155,7 +155,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; struct ieee80211_rate *rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); @@ -278,16 +277,22 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * sequence counter given by mac80211. */ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - spin_lock_irqsave(&intf->seqlock, irqflags); + if (likely(tx_info->control.vif)) { + struct rt2x00_intf *intf; - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - intf->seqno += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + intf = vif_to_intf(tx_info->control.vif); - spin_unlock_irqrestore(&intf->seqlock, irqflags); + spin_lock_irqsave(&intf->seqlock, irqflags); - __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); + if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) + intf->seqno += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + + spin_unlock_irqrestore(&intf->seqlock, irqflags); + + __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); + } } /* diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d6669fd3ffa8..003e4a03874e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -330,6 +330,7 @@ struct ieee80211_tx_info { union { struct { + /* NB: vif can be NULL for injected frames */ struct ieee80211_vif *vif; struct ieee80211_key_conf *hw_key; struct ieee80211_sta *sta; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 698c8233e6b3..c12f361d7185 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -624,7 +624,14 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) u8 *qc; int tid; - /* only for injected frames */ + /* + * Packet injection may want to control the sequence + * number, if we have no matching interface then we + * neither assign one ourselves nor ask the driver to. + */ + if (unlikely(!info->control.vif)) + return TX_CONTINUE; + if (unlikely(ieee80211_is_ctl(hdr->frame_control))) return TX_CONTINUE; @@ -849,7 +856,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, sband = tx->local->hw.wiphy->bands[tx->channel->band]; skb->do_not_encrypt = 1; - info->flags |= IEEE80211_TX_CTL_INJECTED; tx->flags &= ~IEEE80211_TX_FRAGMENTED; /* @@ -981,7 +987,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, /* process and remove the injection radiotap header */ sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { + if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) return TX_DROP; @@ -1300,6 +1306,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct ieee80211_sub_if_data *osdata; int headroom; bool may_encrypt; + enum { + NOT_MONITOR, + FOUND_SDATA, + UNKNOWN_ADDRESS, + } monitor_iface = NOT_MONITOR; int ret; if (skb->iif) @@ -1335,6 +1346,50 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, fwded_frames); } + } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { + struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local = osdata->local; + struct ieee80211_hdr *hdr; + int hdrlen; + u16 len_rthdr; + + info->flags |= IEEE80211_TX_CTL_INJECTED; + monitor_iface = UNKNOWN_ADDRESS; + + len_rthdr = ieee80211_get_radiotap_len(skb->data); + hdr = (struct ieee80211_hdr *)skb->data + len_rthdr; + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + /* check the header is complete in the frame */ + if (likely(skb->len >= len_rthdr + hdrlen)) { + /* + * We process outgoing injected frames that have a + * local address we handle as though they are our + * own frames. + * This code here isn't entirely correct, the local + * MAC address is not necessarily enough to find + * the interface to use; for that proper VLAN/WDS + * support we will need a different mechanism. + */ + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, + list) { + if (!netif_running(sdata->dev)) + continue; + if (compare_ether_addr(sdata->dev->dev_addr, + hdr->addr2)) { + dev_hold(sdata->dev); + dev_put(odev); + osdata = sdata; + odev = osdata->dev; + skb->iif = sdata->dev->ifindex; + monitor_iface = FOUND_SDATA; + break; + } + } + rcu_read_unlock(); + } } may_encrypt = !skb->do_not_encrypt; @@ -1355,7 +1410,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, osdata = container_of(osdata->bss, struct ieee80211_sub_if_data, u.ap); - info->control.vif = &osdata->vif; + if (likely(monitor_iface != UNKNOWN_ADDRESS)) + info->control.vif = &osdata->vif; ret = ieee80211_tx(odev, skb); dev_put(odev); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 6eb222369bcb..f32561ec224c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -231,16 +231,21 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_rate *rate) { struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_sub_if_data *sdata; u16 dur; int erp; + bool short_preamble = false; erp = 0; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = rate->flags & IEEE80211_RATE_ERP_G; + if (vif) { + sdata = vif_to_sdata(vif); + short_preamble = sdata->bss_conf.use_short_preamble; + if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = rate->flags & IEEE80211_RATE_ERP_G; + } dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, - sdata->bss_conf.use_short_preamble); + short_preamble); return cpu_to_le16(dur); } @@ -252,7 +257,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate; - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_sub_if_data *sdata; bool short_preamble; int erp; u16 dur; @@ -260,13 +265,17 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - short_preamble = sdata->bss_conf.use_short_preamble; + short_preamble = false; rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; erp = 0; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = rate->flags & IEEE80211_RATE_ERP_G; + if (vif) { + sdata = vif_to_sdata(vif); + short_preamble = sdata->bss_conf.use_short_preamble; + if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = rate->flags & IEEE80211_RATE_ERP_G; + } /* CTS duration */ dur = ieee80211_frame_duration(local, 10, rate->bitrate, @@ -289,7 +298,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate; - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_sub_if_data *sdata; bool short_preamble; int erp; u16 dur; @@ -297,12 +306,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - short_preamble = sdata->bss_conf.use_short_preamble; + short_preamble = false; rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; erp = 0; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = rate->flags & IEEE80211_RATE_ERP_G; + if (vif) { + sdata = vif_to_sdata(vif); + short_preamble = sdata->bss_conf.use_short_preamble; + if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) + erp = rate->flags & IEEE80211_RATE_ERP_G; + } /* Data frame duration */ dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, -- cgit v1.2.3 From 9222963f7c81e2897833a43066c9db75350c8586 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Sep 2008 09:53:27 +0200 Subject: mac80211: fix sta_info kernel-doc warning Sorry, forgot to run kernel-doc and just got the output from the nightly run by email, this fixes a warning which I introduced when doing the first RC API cleanups. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/sta_info.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b773c7b8d296..daedfa9e1c63 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -197,7 +197,7 @@ struct sta_ampdu_mlme { * @tx_packets: number of RX/TX MSDUs * @tx_bytes: TBD * @tx_fragments: number of transmitted MPDUs - * @txrate_idx: TBD + * @last_txrate_idx: Index of the last used transmit rate * @tid_seq: TBD * @wme_tx_queue: TBD * @ampdu_mlme: TBD -- cgit v1.2.3 From c1b6cf4ee0fb8a3698c563e101a60f9ee4910de0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Sep 2008 11:05:39 +0200 Subject: mac80211: remove beacon counters The beacon counters mac80211 keeps are only used for debugfs, unfortunately, they are incorrect for many hardware designs, namely any design that has a beacon template. Hence, remove the counters so we don't create the impression they are usable. This also allows removing the beacon MESH #ifdef again. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_netdev.c | 6 ------ net/mac80211/ieee80211_i.h | 5 ----- net/mac80211/tx.c | 9 --------- 3 files changed, 20 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 1b33cad24abc..2a4515623776 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -173,7 +173,6 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC); IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); -IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC); static ssize_t ieee80211_if_fmt_flags( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -192,7 +191,6 @@ __IEEE80211_IF_FILE(flags); /* AP attributes */ IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); -IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); static ssize_t ieee80211_if_fmt_num_buffered_multicast( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -265,7 +263,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(auth_alg, sta); DEBUGFS_ADD(auth_transaction, sta); DEBUGFS_ADD(flags, sta); - DEBUGFS_ADD(num_beacons_sta, sta); } static void add_ap_files(struct ieee80211_sub_if_data *sdata) @@ -276,7 +273,6 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(num_sta_ps, ap); DEBUGFS_ADD(dtim_count, ap); - DEBUGFS_ADD(num_beacons, ap); DEBUGFS_ADD(num_buffered_multicast, ap); } @@ -398,7 +394,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_DEL(auth_alg, sta); DEBUGFS_DEL(auth_transaction, sta); DEBUGFS_DEL(flags, sta); - DEBUGFS_DEL(num_beacons_sta, sta); } static void del_ap_files(struct ieee80211_sub_if_data *sdata) @@ -409,7 +404,6 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_DEL(num_sta_ps, ap); DEBUGFS_DEL(dtim_count, ap); - DEBUGFS_DEL(num_beacons, ap); DEBUGFS_DEL(num_buffered_multicast, ap); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6bd6a6306da3..3912fba6d3d0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -229,7 +229,6 @@ struct ieee80211_if_ap { struct sk_buff_head ps_bc_buf; atomic_t num_sta_ps; /* number of stations in PS mode */ int dtim_count; - int num_beacons; /* number of TXed beacon frames for this BSS */ }; struct ieee80211_if_wds { @@ -352,7 +351,6 @@ struct ieee80211_if_sta { u32 supp_rates_bits[IEEE80211_NUM_BANDS]; int wmm_last_param_set; - int num_beacons; /* number of TXed beacon frames by this STA */ }; struct ieee80211_if_mesh { @@ -388,7 +386,6 @@ struct ieee80211_if_mesh { struct mesh_config mshcfg; u32 mesh_seqnum; bool accepting_plinks; - int num_beacons; }; #ifdef CONFIG_MAC80211_MESH @@ -484,7 +481,6 @@ struct ieee80211_sub_if_data { struct dentry *auth_alg; struct dentry *auth_transaction; struct dentry *flags; - struct dentry *num_beacons_sta; struct dentry *force_unicast_rateidx; struct dentry *max_ratectrl_rateidx; } sta; @@ -492,7 +488,6 @@ struct ieee80211_sub_if_data { struct dentry *drop_unencrypted; struct dentry *num_sta_ps; struct dentry *dtim_count; - struct dentry *num_beacons; struct dentry *force_unicast_rateidx; struct dentry *max_ratectrl_rateidx; struct dentry *num_buffered_multicast; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c12f361d7185..d136a371e6bd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1864,7 +1864,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct rate_selection rsel; struct beacon_data *beacon; struct ieee80211_supported_band *sband; - int *num_beacons; enum ieee80211_band band = local->hw.conf.channel->band; sband = local->hw.wiphy->bands[band]; @@ -1912,8 +1911,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, if (beacon->tail) memcpy(skb_put(skb, beacon->tail_len), beacon->tail, beacon->tail_len); - - num_beacons = &ap->num_beacons; } else goto out; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { @@ -1931,8 +1928,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); - num_beacons = &ifsta->num_beacons; -#ifdef CONFIG_MAC80211_MESH } else if (ieee80211_vif_is_mesh(&sdata->vif)) { struct ieee80211_mgmt *mgmt; u8 *pos; @@ -1960,9 +1955,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, *pos++ = 0x0; mesh_mgmt_ies_add(skb, sdata); - - num_beacons = &sdata->u.mesh.num_beacons; -#endif } else { WARN_ON(1); goto out; @@ -1999,7 +1991,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; info->control.retry_limit = 1; - (*num_beacons)++; out: rcu_read_unlock(); return skb; -- cgit v1.2.3 From 538df283c185c477dbdafafa9652c33e9742de75 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Sep 2008 15:22:53 +0200 Subject: mac80211: remove debug frame dumping You can just pull up a monitor interface to get much more detailed information, or, when debugging a driver, insert dump code into the driver (which usually you will have to do anyway to dump the driver-specific information). Hence this option is useless. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 13 ------------- net/mac80211/tx.c | 42 ------------------------------------------ 2 files changed, 55 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 80d693392b0f..8427518e4f20 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -179,19 +179,6 @@ config MAC80211_VERBOSE_MPL_DEBUG Do not select this option. -config MAC80211_LOWTX_FRAME_DUMP - bool "Debug frame dumping" - depends on MAC80211_DEBUG_MENU - ---help--- - Selecting this option will cause the stack to - print a message for each frame that is handed - to the lowlevel driver for transmission. This - message includes all MAC addresses and the - frame control field. - - If unsure, say N and insert the debugging code - you require into the driver you are debugging. - config MAC80211_DEBUG_COUNTERS bool "Extra statistics for TX/RX debugging" depends on MAC80211_DEBUG_MENU diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d136a371e6bd..20d683641b42 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -38,43 +38,6 @@ /* misc utils */ -#ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP -static void ieee80211_dump_frame(const char *ifname, const char *title, - const struct sk_buff *skb) -{ - const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; - DECLARE_MAC_BUF(mac); - - printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); - if (skb->len < 4) { - printk("\n"); - return; - } - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (hdrlen > skb->len) - hdrlen = skb->len; - if (hdrlen >= 4) - printk(" FC=0x%04x DUR=0x%04x", - le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); - if (hdrlen >= 10) - printk(" A1=%s", print_mac(mac, hdr->addr1)); - if (hdrlen >= 16) - printk(" A2=%s", print_mac(mac, hdr->addr2)); - if (hdrlen >= 24) - printk(" A3=%s", print_mac(mac, hdr->addr3)); - if (hdrlen >= 30) - printk(" A4=%s", print_mac(mac, hdr->addr4)); - printk("\n"); -} -#else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ -static inline void ieee80211_dump_frame(const char *ifname, const char *title, - struct sk_buff *skb) -{ -} -#endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ - static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, int next_frag_len) { @@ -1068,8 +1031,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, return IEEE80211_TX_AGAIN; info = IEEE80211_SKB_CB(skb); - ieee80211_dump_frame(wiphy_name(local->hw.wiphy), - "TX to low-level driver", skb); ret = local->ops->tx(local_to_hw(local), skb); if (ret) return IEEE80211_TX_AGAIN; @@ -1099,9 +1060,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; } - ieee80211_dump_frame(wiphy_name(local->hw.wiphy), - "TX to low-level driver", - tx->extra_frag[i]); ret = local->ops->tx(local_to_hw(local), tx->extra_frag[i]); if (ret) -- cgit v1.2.3 From e16ce63c893ff7ccb314d2fbdafbbc915b64d173 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 12 Sep 2008 13:44:08 -0700 Subject: mac80211 : Fix mode change hard_start_xmit function When monitor mode is changed to BSS or IBSS, data trasnfer can not happen because proper transmit function is not assigend for BSS ,IBSS mode. This patch fixes this problem by assigning the ieee80211_subif_start_xmit to device's hard_start_xmit function. Signed-off-by: Abhijeet Kolekar Acked-by: Zhu Yi Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/mac80211') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a7ef0289fbdb..a72fbebb8ea2 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -624,6 +624,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, /* and set some type-dependent values */ sdata->vif.type = type; + sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; /* only monitor differs */ sdata->dev->type = ARPHRD_ETHER; -- cgit v1.2.3 From 6067804047b64dde89f4f133fc7eba48ee44107d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 20 Sep 2008 22:20:49 -0700 Subject: net: Use hton[sl]() instead of __constant_hton[sl]() where applicable Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 2 +- net/atm/br2684.c | 8 ++++---- net/core/dev.c | 4 ++-- net/ethernet/eth.c | 2 +- net/ipv4/ipvs/ip_vs_core.c | 4 ++-- net/ipv6/ip6_tunnel.c | 4 ++-- net/mac80211/wme.c | 2 +- net/sched/cls_flow.c | 28 ++++++++++++++-------------- net/sched/sch_dsmark.c | 8 ++++---- net/sched/sch_sfq.c | 4 ++-- net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++-- 11 files changed, 35 insertions(+), 35 deletions(-) (limited to 'net/mac80211') diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 97688cdb5501..8883e9c8a223 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -48,7 +48,7 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb) switch (veth->h_vlan_encapsulated_proto) { #ifdef CONFIG_INET - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): /* TODO: Confirm this will work with VLAN headers... */ return arp_find(veth->h_dest, skb); diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 8d9a6f158880..280de481edc7 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -375,11 +375,11 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) if (memcmp (skb->data + 6, ethertype_ipv6, sizeof(ethertype_ipv6)) == 0) - skb->protocol = __constant_htons(ETH_P_IPV6); + skb->protocol = htons(ETH_P_IPV6); else if (memcmp (skb->data + 6, ethertype_ipv4, sizeof(ethertype_ipv4)) == 0) - skb->protocol = __constant_htons(ETH_P_IP); + skb->protocol = htons(ETH_P_IP); else goto error; skb_pull(skb, sizeof(llc_oui_ipv4)); @@ -404,9 +404,9 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) skb_reset_network_header(skb); iph = ip_hdr(skb); if (iph->version == 4) - skb->protocol = __constant_htons(ETH_P_IP); + skb->protocol = htons(ETH_P_IP); else if (iph->version == 6) - skb->protocol = __constant_htons(ETH_P_IPV6); + skb->protocol = htons(ETH_P_IPV6); else goto error; skb->pkt_type = PACKET_HOST; diff --git a/net/core/dev.c b/net/core/dev.c index f48d1b24f9ce..fdfc4b6a6448 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1675,13 +1675,13 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) } switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): ip_proto = ip_hdr(skb)->protocol; addr1 = ip_hdr(skb)->saddr; addr2 = ip_hdr(skb)->daddr; ihl = ip_hdr(skb)->ihl; break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): ip_proto = ipv6_hdr(skb)->nexthdr; addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3]; addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3]; diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index a80839b02e3f..647a9edee375 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -129,7 +129,7 @@ int eth_rebuild_header(struct sk_buff *skb) switch (eth->h_proto) { #ifdef CONFIG_INET - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return arp_find(eth->h_dest, skb); #endif default: diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index ece748dbd0cd..958abf3e5f8c 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -938,7 +938,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, EnterFunction(11); - af = (skb->protocol == __constant_htons(ETH_P_IP)) ? AF_INET : AF_INET6; + af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6; if (skb->ipvs_property) return NF_ACCEPT; @@ -1258,7 +1258,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, struct ip_vs_conn *cp; int ret, restart, af; - af = (skb->protocol == __constant_htons(ETH_P_IP)) ? AF_INET : AF_INET6; + af = (skb->protocol == htons(ETH_P_IP)) ? AF_INET : AF_INET6; ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 17c7b098cdb0..64ce3d33d9c6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1050,10 +1050,10 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) } switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): ret = ip4ip6_tnl_xmit(skb, dev); break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): ret = ip6ip6_tnl_xmit(skb, dev); break; default: diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 6748dedcab50..c703f8b44e92 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -39,7 +39,7 @@ static unsigned int classify_1d(struct sk_buff *skb) return skb->priority - 256; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): dscp = ip_hdr(skb)->tos & 0xfc; break; diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index 8f63a1a94014..0ebaff637e31 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c @@ -67,9 +67,9 @@ static inline u32 addr_fold(void *addr) static u32 flow_get_src(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(ip_hdr(skb)->saddr); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(ipv6_hdr(skb)->saddr.s6_addr32[3]); default: return addr_fold(skb->sk); @@ -79,9 +79,9 @@ static u32 flow_get_src(const struct sk_buff *skb) static u32 flow_get_dst(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(ip_hdr(skb)->daddr); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(ipv6_hdr(skb)->daddr.s6_addr32[3]); default: return addr_fold(skb->dst) ^ (__force u16)skb->protocol; @@ -91,9 +91,9 @@ static u32 flow_get_dst(const struct sk_buff *skb) static u32 flow_get_proto(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ip_hdr(skb)->protocol; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ipv6_hdr(skb)->nexthdr; default: return 0; @@ -120,7 +120,7 @@ static u32 flow_get_proto_src(const struct sk_buff *skb) u32 res = 0; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): { + case htons(ETH_P_IP): { struct iphdr *iph = ip_hdr(skb); if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && @@ -128,7 +128,7 @@ static u32 flow_get_proto_src(const struct sk_buff *skb) res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4)); break; } - case __constant_htons(ETH_P_IPV6): { + case htons(ETH_P_IPV6): { struct ipv6hdr *iph = ipv6_hdr(skb); if (has_ports(iph->nexthdr)) @@ -147,7 +147,7 @@ static u32 flow_get_proto_dst(const struct sk_buff *skb) u32 res = 0; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): { + case htons(ETH_P_IP): { struct iphdr *iph = ip_hdr(skb); if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && @@ -155,7 +155,7 @@ static u32 flow_get_proto_dst(const struct sk_buff *skb) res = ntohs(*(__be16 *)((void *)iph + iph->ihl * 4 + 2)); break; } - case __constant_htons(ETH_P_IPV6): { + case htons(ETH_P_IPV6): { struct ipv6hdr *iph = ipv6_hdr(skb); if (has_ports(iph->nexthdr)) @@ -213,9 +213,9 @@ static u32 flow_get_nfct(const struct sk_buff *skb) static u32 flow_get_nfct_src(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(CTTUPLE(skb, src.u3.ip)); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(CTTUPLE(skb, src.u3.ip6[3])); } fallback: @@ -225,9 +225,9 @@ fallback: static u32 flow_get_nfct_dst(const struct sk_buff *skb) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): return ntohl(CTTUPLE(skb, dst.u3.ip)); - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): return ntohl(CTTUPLE(skb, dst.u3.ip6[3])); } fallback: diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index edd1298f85f6..ba43aab3a851 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -202,7 +202,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (p->set_tc_index) { switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): if (skb_cow_head(skb, sizeof(struct iphdr))) goto drop; @@ -210,7 +210,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) & ~INET_ECN_MASK; break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): if (skb_cow_head(skb, sizeof(struct ipv6hdr))) goto drop; @@ -289,11 +289,11 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) pr_debug("index %d->%d\n", skb->tc_index, index); switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): ipv4_change_dsfield(ip_hdr(skb), p->mask[index], p->value[index]); break; - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): ipv6_change_dsfield(ipv6_hdr(skb), p->mask[index], p->value[index]); break; diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 6e041d10dbdb..fe1508ef0d3d 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -119,7 +119,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) u32 h, h2; switch (skb->protocol) { - case __constant_htons(ETH_P_IP): + case htons(ETH_P_IP): { const struct iphdr *iph = ip_hdr(skb); h = iph->daddr; @@ -134,7 +134,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) h2 ^= *(((u32*)iph) + iph->ihl); break; } - case __constant_htons(ETH_P_IPV6): + case htons(ETH_P_IPV6): { struct ipv6hdr *iph = ipv6_hdr(skb); h = iph->daddr.s6_addr32[3]; diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index e55427f73dfe..5c1954d28d09 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c @@ -769,7 +769,7 @@ repost: /* check for expected message types */ /* The order of some of these tests is important. */ switch (headerp->rm_type) { - case __constant_htonl(RDMA_MSG): + case htonl(RDMA_MSG): /* never expect read chunks */ /* never expect reply chunks (two ways to check) */ /* never expect write chunks without having offered RDMA */ @@ -802,7 +802,7 @@ repost: rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len); break; - case __constant_htonl(RDMA_NOMSG): + case htonl(RDMA_NOMSG): /* never expect read or write chunks, always reply chunks */ if (headerp->rm_body.rm_chunks[0] != xdr_zero || headerp->rm_body.rm_chunks[1] != xdr_zero || -- cgit v1.2.3 From 133b822638ff01eb1e32e1917b197c40ed095ddd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 14:18:59 +0200 Subject: mac80211: make master iface not wireless There's no need to register the master netdev with cfg80211, in fact, this is quite dangerous and lead to having to add checks for the master interface all over the config handlers. This patch removes the "ieee80211_ptr" from the master iface in favour of having a small netdev_priv() associated with the master interface that stores the ieee80211_local pointer. Because of this, a lot of code in the configuration handlers can go away. To make this patch easier to verify I have also removed a number of wiphy_priv() calls in favour of getting the sdata first and then the local pointer from that. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 59 ---------------------------------------------- net/mac80211/debugfs_sta.c | 3 +-- net/mac80211/ieee80211_i.h | 4 ++++ net/mac80211/main.c | 19 ++++++++------- net/mac80211/mesh.c | 2 +- net/mac80211/rx.c | 25 ++++++++------------ net/mac80211/tx.c | 26 ++++++++++---------- 7 files changed, 39 insertions(+), 99 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e2574885db4a..a8501f14b167 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct net_device *dev; struct ieee80211_sub_if_data *sdata; int ret; @@ -95,9 +94,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, if (!nl80211_type_check(type)) return -EINVAL; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ret = ieee80211_if_change_type(sdata, type); @@ -120,16 +116,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, u8 *mac_addr, struct key_params *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; enum ieee80211_key_alg alg; struct ieee80211_key *key; int err; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); switch (params->cipher) { @@ -174,14 +166,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, u8 *mac_addr) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; int ret; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -222,7 +210,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, void (*callback)(void *cookie, struct key_params *params)) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; u8 seq[6] = {0}; @@ -232,9 +219,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, u16 iv16; int err = -ENOENT; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -310,12 +294,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; - if (dev == local->mdev) - return -EOPNOTSUPP; - rcu_read_lock(); sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -496,13 +476,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -519,13 +495,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -541,13 +513,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -695,9 +663,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; int err; - if (dev == local->mdev || params->vlan == local->mdev) - return -EOPNOTSUPP; - /* Prevent a race with changing the rate control algorithm */ if (!netif_running(dev)) return -ENETDOWN; @@ -752,9 +717,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (mac) { @@ -786,9 +748,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; - if (dev == local->mdev || params->vlan == local->mdev) - return -EOPNOTSUPP; - rcu_read_lock(); /* XXX: get sta belonging to dev */ @@ -828,9 +787,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, struct sta_info *sta; int err; - if (dev == local->mdev) - return -EOPNOTSUPP; - if (!netif_running(dev)) return -ENETDOWN; @@ -884,9 +840,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, struct mesh_path *mpath; struct sta_info *sta; - if (dev == local->mdev) - return -EOPNOTSUPP; - if (!netif_running(dev)) return -ENETDOWN; @@ -958,13 +911,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -986,13 +935,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -1015,13 +960,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; u32 changed = 0; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 81f350eaf8a3..b9902e425f09 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sta_info *sta = file->private_data; - struct net_device *dev = sta->sdata->dev; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sta->sdata->local; struct ieee80211_hw *hw = &local->hw; u8 *da = sta->sta.addr; static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3912fba6d3d0..0b25b0f46b1a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -573,6 +573,10 @@ enum { /* maximum number of hardware queues we support. */ #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) +struct ieee80211_master_priv { + struct ieee80211_local *local; +}; + struct ieee80211_local { /* embed the driver visible part. * don't cast (use the static inlines below), but we keep diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c307dba7ec03..7d2d5a041e26 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = { static int ieee80211_master_open(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_sub_if_data *sdata; int res = -EOPNOTSUPP; @@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) static int ieee80211_master_stop(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_sub_if_data *sdata; /* we hold the RTNL here so can safely walk the list */ @@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev) static void ieee80211_master_set_multicast_list(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; ieee80211_configure_filter(local); } @@ -787,7 +790,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int result; enum ieee80211_band band; struct net_device *mdev; - struct wireless_dev *mwdev; + struct ieee80211_master_priv *mpriv; /* * generic code guarantees at least one band, @@ -829,16 +832,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (hw->queues < 4) hw->ampdu_queues = 0; - mdev = alloc_netdev_mq(sizeof(struct wireless_dev), + mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), "wmaster%d", ether_setup, ieee80211_num_queues(hw)); if (!mdev) goto fail_mdev_alloc; - mwdev = netdev_priv(mdev); - mdev->ieee80211_ptr = mwdev; - mwdev->wiphy = local->hw.wiphy; - + mpriv = netdev_priv(mdev); + mpriv->local = local; local->mdev = mdev; ieee80211_rx_bss_list_init(local); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 30cf891fd3a8..8013277924f2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct ieee80211_local *local = wdev_priv(&sdata->wdev); + struct ieee80211_local *local = sdata->local; queue_work(local->hw.workqueue, &ifmsh->work); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 92d898b901e9..3ab9670f1809 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) return result; } -static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) +static void ap_sta_ps_start(struct sta_info *sta) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = sta->sdata; DECLARE_MAC_BUF(mac); - sdata = sta->sdata; - atomic_inc(&sdata->bss->num_sta_ps); set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", - dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); + sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } -static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) +static int ap_sta_ps_end(struct sta_info *sta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; int sent = 0; - struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_info *info; DECLARE_MAC_BUF(mac); - sdata = sta->sdata; - atomic_dec(&sdata->bss->num_sta_ps); clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); @@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", - dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); + sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ @@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) sent++; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " - "since STA not sleeping anymore\n", dev->name, + "since STA not sleeping anymore\n", sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ info->flags |= IEEE80211_TX_CTL_REQUEUE; @@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) { struct sta_info *sta = rx->sta; - struct net_device *dev = rx->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; if (!sta) @@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) * exchange sequence */ if (test_sta_flags(sta, WLAN_STA_PS) && !ieee80211_has_pm(hdr->frame_control)) - rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); + rx->sent_ps_buffered += ap_sta_ps_end(sta); else if (!test_sta_flags(sta, WLAN_STA_PS) && ieee80211_has_pm(hdr->frame_control)) - ap_sta_ps_start(dev, sta); + ap_sta_ps_start(sta); } /* Drop data::nullfunc frames silently, since they are used only to diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b42..00d798cc9e04 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, return cpu_to_le16(dur); } -static int inline is_ieee80211_device(struct net_device *dev, - struct net_device *master) +static int inline is_ieee80211_device(struct ieee80211_local *local, + struct net_device *dev) { - return (wdev_priv(dev->ieee80211_ptr) == - wdev_priv(master->ieee80211_ptr)); + return local == wdev_priv(dev->ieee80211_ptr); } /* tx handlers */ @@ -1001,14 +1000,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, /* * NB: @tx is uninitialised when passed in here */ -static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, - struct sk_buff *skb, - struct net_device *mdev) +static int ieee80211_tx_prepare(struct ieee80211_local *local, + struct ieee80211_tx_data *tx, + struct sk_buff *skb) { struct net_device *dev; dev = dev_get_by_index(&init_net, skb->iif); - if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { + if (unlikely(dev && !is_ieee80211_device(local, dev))) { dev_put(dev); dev = NULL; } @@ -1258,6 +1257,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) { + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct net_device *odev = NULL; @@ -1273,7 +1274,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (skb->iif) odev = dev_get_by_index(&init_net, skb->iif); - if (unlikely(odev && !is_ieee80211_device(odev, dev))) { + if (unlikely(odev && !is_ieee80211_device(local, odev))) { dev_put(odev); odev = NULL; } @@ -1449,8 +1450,8 @@ fail: int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int ret = 1, head_need; u16 ethertype, hdrlen, meshhdrlen = 0; __le16 fc; @@ -1462,7 +1463,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct sta_info *sta; u32 sta_flags = 0; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (unlikely(skb->len < ETH_HLEN)) { ret = 0; goto fail; @@ -2032,7 +2032,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, cpu_to_le16(IEEE80211_FCTL_MOREDATA); } - if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) + if (!ieee80211_tx_prepare(local, &tx, skb)) break; dev_kfree_skb_any(skb); } -- cgit v1.2.3 From 60719ffd721f6764b7d07ca188c0d944a4330b69 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 14:55:09 +0200 Subject: cfg80211: show interface type This patch makes cfg80211 show the interface in the nl80211 information about a specific interface. API users are required to keep the type updated (everything else is fairly complicated) but you will get a warning if you fail to keep it updated. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 6 ++++-- include/net/wireless.h | 2 ++ net/mac80211/iface.c | 1 + net/wireless/core.c | 2 ++ net/wireless/nl80211.c | 6 +++++- 5 files changed, 14 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9f40c4d417d7..0e85ec39b638 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -363,11 +363,13 @@ struct wiphy; * wireless extensions but this is subject to reevaluation as soon as this * code is used more widely and we have a first user without wext. * - * @add_virtual_intf: create a new virtual interface with the given name + * @add_virtual_intf: create a new virtual interface with the given name, + * must set the struct wireless_dev's iftype. * * @del_virtual_intf: remove the virtual interface determined by ifindex. * - * @change_virtual_intf: change type of virtual interface + * @change_virtual_intf: change type/configuration of virtual interface, + * keep the struct wireless_dev's iftype updated. * * @add_key: add a key with the given parameters. @mac_addr will be %NULL * when adding a group key. diff --git a/include/net/wireless.h b/include/net/wireless.h index 0de7fde9f336..721efb363db7 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -223,9 +223,11 @@ struct wiphy { * the netdev.) * * @wiphy: pointer to hardware description + * @iftype: interface type */ struct wireless_dev { struct wiphy *wiphy; + enum nl80211_iftype iftype; /* private to the generic wireless code */ struct list_head list; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a72fbebb8ea2..b5cd91e89712 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -625,6 +625,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, /* and set some type-dependent values */ sdata->vif.type = type; sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; + sdata->wdev.iftype = type; /* only monitor differs */ sdata->dev->type = ARPHRD_ETHER; diff --git a/net/wireless/core.c b/net/wireless/core.c index 88cb73394864..d6940085d59c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -384,6 +384,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); + WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED); + switch (state) { case NETDEV_REGISTER: mutex_lock(&rdev->devlist_mtx); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1221d726ed50..44771a690d53 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -299,7 +299,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); - /* TODO: interface type */ + NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); return genlmsg_end(msg, hdr); nla_put_failure: @@ -453,6 +453,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) &flags); err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type, err ? NULL : &flags, ¶ms); + + dev = __dev_get_by_index(&init_net, ifindex); + WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); + rtnl_unlock(); unlock: -- cgit v1.2.3 From f8b25cdad719cddceb9cf0d350065b3e59e74219 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 20:22:21 +0200 Subject: mac80211: allow interface settings changes only when down We currently allow monitor flags changes and mesh ID changes when the interface is up, which can lead to trouble. Change it to only allow when down. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a8501f14b167..89a183c2327a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -100,6 +100,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, if (ret) return ret; + if (netif_running(sdata->dev)) + return -EBUSY; + if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) ieee80211_sdata_set_mesh_id(sdata, params->mesh_id_len, -- cgit v1.2.3 From 79617deeebb9cf089e2bc2aad19743b1209043f6 Mon Sep 17 00:00:00 2001 From: YanBo Date: Mon, 22 Sep 2008 13:30:32 +0800 Subject: mac80211: mesh portal functionality support Currently the mesh code doesn't support bridging mesh point interfaces with wired ethernet or AP to construct an MPP or MAP. This patch adds code to support the "6 address frame format packet" functionality to mesh point interfaces. Now the mesh network can be used as backhaul for end to end communication. Signed-off-by: Li YanBo Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 5 ++ net/mac80211/mesh.h | 4 ++ net/mac80211/mesh_pathtbl.c | 127 +++++++++++++++++++++++++++++++++++++++++++- net/mac80211/rx.c | 32 +++++++++-- net/mac80211/tx.c | 44 ++++++++++++--- 5 files changed, 201 insertions(+), 11 deletions(-) (limited to 'net/mac80211') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index abc1abc63bf0..14126bc36641 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -471,6 +471,11 @@ struct ieee80211s_hdr { u8 eaddr3[6]; } __attribute__ ((packed)); +/* Mesh flags */ +#define MESH_FLAGS_AE_A4 0x1 +#define MESH_FLAGS_AE_A5_A6 0x2 +#define MESH_FLAGS_PS_DEEP 0x4 + /** * struct ieee80211_quiet_ie * diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8ee414a0447c..e10471c6ba42 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -71,6 +71,7 @@ enum mesh_path_flags { */ struct mesh_path { u8 dst[ETH_ALEN]; + u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ struct ieee80211_sub_if_data *sdata; struct sta_info *next_hop; struct timer_list timer; @@ -226,6 +227,9 @@ int mesh_nexthop_lookup(struct sk_buff *skb, void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata); +struct mesh_path *mpp_path_lookup(u8 *dst, + struct ieee80211_sub_if_data *sdata); +int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata); void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index e4fa2905fadc..3c72557df45a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -36,6 +36,7 @@ struct mpath_node { }; static struct mesh_table *mesh_paths; +static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ /* This lock will have the grow table function as writer and add / delete nodes * as readers. When reading the table (i.e. doing lookups) we are well protected @@ -94,6 +95,34 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) return NULL; } +struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) +{ + struct mesh_path *mpath; + struct hlist_node *n; + struct hlist_head *bucket; + struct mesh_table *tbl; + struct mpath_node *node; + + tbl = rcu_dereference(mpp_paths); + + bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; + hlist_for_each_entry_rcu(node, n, bucket, list) { + mpath = node->mpath; + if (mpath->sdata == sdata && + memcmp(dst, mpath->dst, ETH_ALEN) == 0) { + if (MPATH_EXPIRED(mpath)) { + spin_lock_bh(&mpath->state_lock); + if (MPATH_EXPIRED(mpath)) + mpath->flags &= ~MESH_PATH_ACTIVE; + spin_unlock_bh(&mpath->state_lock); + } + return mpath; + } + } + return NULL; +} + + /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index * @idx: index @@ -226,6 +255,91 @@ err_path_alloc: } +int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) +{ + struct mesh_path *mpath, *new_mpath; + struct mpath_node *node, *new_node; + struct hlist_head *bucket; + struct hlist_node *n; + int grow = 0; + int err = 0; + u32 hash_idx; + + + if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) + /* never add ourselves as neighbours */ + return -ENOTSUPP; + + if (is_multicast_ether_addr(dst)) + return -ENOTSUPP; + + err = -ENOMEM; + new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); + if (!new_mpath) + goto err_path_alloc; + + new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); + if (!new_node) + goto err_node_alloc; + + read_lock(&pathtbl_resize_lock); + memcpy(new_mpath->dst, dst, ETH_ALEN); + memcpy(new_mpath->mpp, mpp, ETH_ALEN); + new_mpath->sdata = sdata; + new_mpath->flags = 0; + skb_queue_head_init(&new_mpath->frame_queue); + new_node->mpath = new_mpath; + new_mpath->exp_time = jiffies; + spin_lock_init(&new_mpath->state_lock); + + hash_idx = mesh_table_hash(dst, sdata, mpp_paths); + bucket = &mpp_paths->hash_buckets[hash_idx]; + + spin_lock(&mpp_paths->hashwlock[hash_idx]); + + err = -EEXIST; + hlist_for_each_entry(node, n, bucket, list) { + mpath = node->mpath; + if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) + goto err_exists; + } + + hlist_add_head_rcu(&new_node->list, bucket); + if (atomic_inc_return(&mpp_paths->entries) >= + mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) + grow = 1; + + spin_unlock(&mpp_paths->hashwlock[hash_idx]); + read_unlock(&pathtbl_resize_lock); + if (grow) { + struct mesh_table *oldtbl, *newtbl; + + write_lock(&pathtbl_resize_lock); + oldtbl = mpp_paths; + newtbl = mesh_table_grow(mpp_paths); + if (!newtbl) { + write_unlock(&pathtbl_resize_lock); + return 0; + } + rcu_assign_pointer(mpp_paths, newtbl); + write_unlock(&pathtbl_resize_lock); + + synchronize_rcu(); + mesh_table_free(oldtbl, false); + } + return 0; + +err_exists: + spin_unlock(&mpp_paths->hashwlock[hash_idx]); + read_unlock(&pathtbl_resize_lock); + kfree(new_node); +err_node_alloc: + kfree(new_mpath); +err_path_alloc: + return err; +} + + /** * mesh_plink_broken - deactivates paths and sends perr when a link breaks * @@ -475,11 +589,21 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) int mesh_pathtbl_init(void) { mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + if (!mesh_paths) + return -ENOMEM; mesh_paths->free_node = &mesh_path_node_free; mesh_paths->copy_node = &mesh_path_node_copy; mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; - if (!mesh_paths) + + mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); + if (!mpp_paths) { + mesh_table_free(mesh_paths, true); return -ENOMEM; + } + mpp_paths->free_node = &mesh_path_node_free; + mpp_paths->copy_node = &mesh_path_node_copy; + mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; + return 0; } @@ -511,4 +635,5 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) void mesh_pathtbl_unregister(void) { mesh_table_free(mesh_paths, true); + mesh_table_free(mpp_paths, true); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3ab9670f1809..2efa4dd47b5d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1107,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (ieee80211_vif_is_mesh(&sdata->vif)) - hdrlen += ieee80211_get_mesh_hdrlen( - (struct ieee80211s_hdr *) (skb->data + hdrlen)); - /* convert IEEE 802.11 header + possible LLC headers into Ethernet * header * IEEE 802.11 address fields: @@ -1134,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) return -1; + if (ieee80211_vif_is_mesh(&sdata->vif)) { + struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) + (skb->data + hdrlen); + hdrlen += ieee80211_get_mesh_hdrlen(meshdr); + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { + memcpy(dst, meshdr->eaddr1, ETH_ALEN); + memcpy(src, meshdr->eaddr2, ETH_ALEN); + } + } break; case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): if (sdata->vif.type != NL80211_IFTYPE_STATION || @@ -1393,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) /* illegal frame */ return RX_DROP_MONITOR; + if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ + struct ieee80211_sub_if_data *sdata; + struct mesh_path *mppath; + + sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); + rcu_read_lock(); + mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); + if (!mppath) { + mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); + } else { + spin_lock_bh(&mppath->state_lock); + mppath->exp_time = jiffies; + if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) + memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); + spin_unlock_bh(&mppath->state_lock); + } + rcu_read_unlock(); + } + if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) return RX_CONTINUE; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 00d798cc9e04..00d96e63dce9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1498,18 +1498,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); - /* RA TA DA SA */ - memset(hdr.addr1, 0, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); - memcpy(hdr.addr3, skb->data, ETH_ALEN); - memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { /* Do not send frames with mesh_ttl == 0 */ sdata->u.mesh.mshstats.dropped_frames_ttl++; ret = 0; goto fail; } - meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); + memset(&mesh_hdr, 0, sizeof(mesh_hdr)); + + if (compare_ether_addr(dev->dev_addr, + skb->data + ETH_ALEN) == 0) { + /* RA TA DA SA */ + memset(hdr.addr1, 0, ETH_ALEN); + memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr3, skb->data, ETH_ALEN); + memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); + meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); + } else { + /* packet from other interface */ + struct mesh_path *mppath; + + memset(hdr.addr1, 0, ETH_ALEN); + memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); + + if (is_multicast_ether_addr(skb->data)) + memcpy(hdr.addr3, skb->data, ETH_ALEN); + else { + rcu_read_lock(); + mppath = mpp_path_lookup(skb->data, sdata); + if (mppath) + memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); + else + memset(hdr.addr3, 0xff, ETH_ALEN); + rcu_read_unlock(); + } + + mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; + mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; + put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); + memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); + memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); + sdata->u.mesh.mesh_seqnum++; + meshhdrlen = 18; + } hdrlen = 30; break; #endif -- cgit v1.2.3 From 2ff6a6d4e92270283432690adf53a7e5ab186d19 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Sep 2008 12:24:20 +0200 Subject: mac80211: fix mesh action frame handling When I split off the action frame handling I made the code drop all action frames we don't want to handle. This is wrong since some action frames are actually handled via rx_h_mgmt through being queued to the sta/mesh implementations. Thanks to Li YanBo for noticing the problem. Signed-off-by: Johannes Berg Cc: Li YanBo Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2efa4dd47b5d..c489865761bc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1557,7 +1557,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) */ if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_ADHOC) - return RX_DROP_MONITOR; + return RX_CONTINUE; switch (mgmt->u.action.category) { case WLAN_CATEGORY_BACK: -- cgit v1.2.3 From 4b7679a561e552eeda1e3567119bef2bca99b66e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Sep 2008 18:14:18 +0200 Subject: mac80211: clean up rate control API Long awaited, hard work. This patch totally cleans up the rate control API to remove the requirement to include internal headers outside of net/mac80211/. There's one internal use in the PID algorithm left for mesh networking, we'll have to figure out a way to clean that one up and decide how to do the peer link evaluation, possibly independent of the rate control algorithm or via new API. Additionally, ath9k is left using the cross-inclusion hack for now, we will add new API where necessary to make this work properly, but right now I'm not expert enough to do it. It's still off better than before. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/rc.c | 98 +++++++-------- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 182 ++++++---------------------- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 9 -- drivers/net/wireless/iwlwifi/iwl-3945.h | 4 + drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 146 +++++++++------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 +- include/net/mac80211.h | 68 +++++++++++ net/mac80211/cfg.c | 2 +- net/mac80211/ieee80211_i.h | 2 + net/mac80211/main.c | 4 +- net/mac80211/mlme.c | 4 +- net/mac80211/rate.c | 71 ++++++++--- net/mac80211/rate.h | 102 ++++------------ net/mac80211/rc80211_pid.h | 2 - net/mac80211/rc80211_pid_algo.c | 158 +++++++++--------------- net/mac80211/sta_info.c | 17 +-- net/mac80211/sta_info.h | 2 +- net/mac80211/tx.c | 5 +- 18 files changed, 373 insertions(+), 514 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 1cc9daf44550..cca2fc5b0765 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -20,6 +20,7 @@ */ #include "core.h" +/* FIXME: remove this include! */ #include "../net/mac80211/rate.h" static u32 tx_triglevel_max; @@ -1812,20 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) } -static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) +static void ath_setup_rates(struct ath_softc *sc, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct ath_rate_node *rc_priv) { - struct ieee80211_supported_band *sband; - struct ieee80211_hw *hw = local_to_hw(local); - struct ath_softc *sc = hw->priv; - struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; int i, j = 0; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; for (i = 0; i < sband->n_bitrates; i++) { - if (sta->sta.supp_rates[local->hw.conf.channel->band] & BIT(i)) { + if (sta->supp_rates[sband->band] & BIT(i)) { rc_priv->neg_rates.rs_rates[j] = (sband->bitrates[i].bitrate * 2) / 10; j++; @@ -1852,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) } /* Rate Control callbacks */ -static void ath_tx_status(void *priv, struct net_device *dev, +static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { struct ath_softc *sc = priv; struct ath_tx_info_priv *tx_info_priv; struct ath_node *an; - struct sta_info *sta; - struct ieee80211_local *local; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr; __le16 fc; - local = hw_to_local(sc->hw); hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; @@ -1873,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev, an = ath_node_find(sc, hdr->addr1); spin_unlock_bh(&sc->node_lock); - sta = sta_info_get(local, hdr->addr1); - if (!an || !sta || !ieee80211_is_data(fc)) { + if (!an || !priv_sta || !ieee80211_is_data(fc)) { if (tx_info->driver_data[0] != NULL) { kfree(tx_info->driver_data[0]); tx_info->driver_data[0] = NULL; @@ -1882,24 +1878,22 @@ static void ath_tx_status(void *priv, struct net_device *dev, return; } if (tx_info->driver_data[0] != NULL) { - ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv); + ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); kfree(tx_info->driver_data[0]); tx_info->driver_data[0] = NULL; } } static void ath_tx_aggr_resp(struct ath_softc *sc, - struct sta_info *sta, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, struct ath_node *an, u8 tidno) { - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_local *local; struct ath_atx_tid *txtid; - struct ieee80211_supported_band *sband; u16 buffersize = 0; int state; - DECLARE_MAC_BUF(mac); + struct sta_info *si; if (!(sc->sc_flags & SC_OP_TXAGGR)) return; @@ -1908,11 +1902,16 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, if (!txtid->paused) return; - local = hw_to_local(sc->hw); - sband = hw->wiphy->bands[hw->conf.channel->band]; + /* + * XXX: This is entirely busted, we aren't supposed to + * access the sta from here because it's internal + * to mac80211, and looking at the state without + * locking is wrong too. + */ + si = container_of(sta, struct sta_info, sta); buffersize = IEEE80211_MIN_AMPDU_BUF << sband->ht_info.ampdu_factor; /* FIXME */ - state = sta->ampdu_mlme.tid_state_tx[tidno]; + state = si->ampdu_mlme.tid_state_tx[tidno]; if (state & HT_ADDBA_RECEIVED_MSK) { txtid->addba_exchangecomplete = 1; @@ -1928,18 +1927,15 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, } } -static void ath_get_rate(void *priv, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct sta_info *sta; - struct ath_softc *sc = (struct ath_softc *)priv; + struct ath_softc *sc = priv; struct ieee80211_hw *hw = sc->hw; struct ath_tx_info_priv *tx_info_priv; - struct ath_rate_node *ath_rc_priv; + struct ath_rate_node *ath_rc_priv = priv_sta; struct ath_node *an; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int is_probe = FALSE, chk, ret; @@ -1955,8 +1951,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, ASSERT(tx_info->driver_data[0] != NULL); tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; - sta = sta_info_get(local, hdr->addr1); - lowest_idx = rate_lowest_index(local, sband, sta); + lowest_idx = rate_lowest_index(sband, sta); tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; /* lowest rate for management and multicast/broadcast frames */ if (!ieee80211_is_data(fc) || @@ -1965,8 +1960,6 @@ static void ath_get_rate(void *priv, struct net_device *dev, return; } - ath_rc_priv = sta->rate_ctrl_priv; - /* Find tx rate for unicast frames */ ath_rate_findrate(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4, @@ -1975,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, &is_probe, false); if (is_probe) - sel->probe_idx = ((struct ath_tx_ratectrl *) - sta->rate_ctrl_priv)->probe_rate; + sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; /* Ratecontrol sometimes returns invalid rate index */ if (tx_info_priv->rcs[0].rix != 0xff) @@ -2020,37 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev, __func__, print_mac(mac, hdr->addr1)); } else if (chk == AGGR_EXCHANGE_PROGRESS) - ath_tx_aggr_resp(sc, sta, an, tid); + ath_tx_aggr_resp(sc, sband, sta, an, tid); } } } -static void ath_rate_init(void *priv, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { - struct ieee80211_supported_band *sband; - struct ieee80211_hw *hw = local_to_hw(local); - struct ieee80211_conf *conf = &local->hw.conf; - struct ath_softc *sc = hw->priv; + struct ath_softc *sc = priv; struct ath_rate_node *ath_rc_priv = priv_sta; int i, j = 0; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - ath_setup_rates(local, sta); - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + ath_setup_rates(sc, sband, sta, ath_rc_priv); + if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { for (i = 0; i < MCS_SET_SIZE; i++) { - if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) + if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; if (j == ATH_RATE_MAX) break; } ath_rc_priv->neg_ht_rates.rs_nrates = j; } - ath_rc_node_update(hw, priv_sta); + ath_rc_node_update(sc->hw, priv_sta); } static void ath_rate_clear(void *priv) @@ -2058,13 +2044,12 @@ static void ath_rate_clear(void *priv) return; } -static void *ath_rate_alloc(struct ieee80211_local *local) +static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - struct ieee80211_hw *hw = local_to_hw(local); struct ath_softc *sc = hw->priv; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - return local->hw.priv; + return hw->priv; } static void ath_rate_free(void *priv) @@ -2072,7 +2057,7 @@ static void ath_rate_free(void *priv) return; } -static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) +static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) { struct ath_softc *sc = priv; struct ath_vap *avp = sc->sc_vaps[0]; @@ -2092,7 +2077,8 @@ static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) return rate_priv; } -static void ath_rate_free_sta(void *priv, void *priv_sta) +static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { struct ath_rate_node *rate_priv = priv_sta; struct ath_softc *sc = priv; @@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = { .alloc = ath_rate_alloc, .free = ath_rate_free, .alloc_sta = ath_rate_alloc_sta, - .free_sta = ath_rate_free_sta + .free_sta = ath_rate_free_sta, }; int ath_rate_control_register(void) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a279bf1dc9b0..6fc5e7361f26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -36,8 +36,6 @@ #include -#include "../net/mac80211/rate.h" - #include "iwl-3945.h" #define RS_NAME "iwl-3945-rs" @@ -319,10 +317,10 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, } } -static void rs_rate_init(void *priv_rate, void *priv_sta, - struct ieee80211_local *local, struct sta_info *sta) +static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { - struct iwl3945_rs_sta *rs_sta = (void *)sta->rate_ctrl_priv; + struct iwl3945_rs_sta *rs_sta = priv_sta; int i; IWL_DEBUG_RATE("enter\n"); @@ -333,22 +331,22 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { - if (sta->sta.supp_rates[local->hw.conf.channel->band] & (1 << i)) { + if (sta->supp_rates[sband->band] & (1 << i)) { rs_sta->last_txrate_idx = i; break; } } /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + if (sband->band == IEEE80211_BAND_5GHZ) rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE("leave\n"); } -static void *rs_alloc(struct ieee80211_local *local) +static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - return local->hw.priv; + return hw->priv; } /* rate scale requires free function to be implemented */ @@ -356,17 +354,24 @@ static void rs_free(void *priv) { return; } + static void rs_clear(void *priv) { return; } -static void *rs_alloc_sta(void *priv, gfp_t gfp) +static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; + struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; int i; + /* + * XXX: If it's using sta->drv_priv anyway, it might + * as well just put all the information there. + */ + IWL_DEBUG_RATE("enter\n"); rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); @@ -375,6 +380,8 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) return NULL; } + psta->rs_sta = rs_sta; + spin_lock_init(&rs_sta->lock); rs_sta->start_rate = IWL_RATE_INVALID; @@ -400,10 +407,14 @@ static void *rs_alloc_sta(void *priv, gfp_t gfp) return rs_sta; } -static void rs_free_sta(void *priv, void *priv_sta) +static void rs_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { + struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; + psta->rs_sta = NULL; + IWL_DEBUG_RATE("enter\n"); del_timer_sync(&rs_sta->rate_scale_flush); kfree(rs_sta); @@ -445,26 +456,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by * the hardware for each rate. */ -static void rs_tx_status(void *priv_rate, - struct net_device *dev, +static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { u8 retries, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; - struct sta_info *sta; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct iwl3945_rs_sta *rs_sta; - struct ieee80211_supported_band *sband; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - retries = info->status.retry_count; first_index = sband->bitrates[info->tx_rate_idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { @@ -472,17 +476,11 @@ static void rs_tx_status(void *priv_rate, return; } - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - if (!sta || !sta->rate_ctrl_priv) { - rcu_read_unlock(); + if (!priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); return; } - rs_sta = (void *)sta->rate_ctrl_priv; - rs_sta->tx_packets++; scale_rate_index = first_index; @@ -549,8 +547,6 @@ static void rs_tx_status(void *priv_rate, spin_unlock_irqrestore(&rs_sta->lock, flags); - rcu_read_unlock(); - IWL_DEBUG_RATE("leave\n"); return; @@ -634,16 +630,15 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * rate table and must reference the driver allocated rate table * */ -static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { u8 low = IWL_RATE_INVALID; u8 high = IWL_RATE_INVALID; u16 high_low; int index; - struct iwl3945_rs_sta *rs_sta; + struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl3945_rate_scale_data *window = NULL; int current_tpt = IWL_INV_TPT; int low_tpt = IWL_INV_TPT; @@ -651,34 +646,25 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, u32 fail_count; s8 scale_action = 0; unsigned long flags; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct sta_info *sta; u16 fc, rate_mask; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; + struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; DECLARE_MAC_BUF(mac); IWL_DEBUG_RATE("enter\n"); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1) || - !sta || !sta->rate_ctrl_priv) { + !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate_idx = rate_lowest_index(local, sband, sta); - rcu_read_unlock(); + sel->rate_idx = rate_lowest_index(sband, sta); return; } - rs_sta = (void *)sta->rate_ctrl_priv; - - rate_mask = sta->sta.supp_rates[sband->band]; + rate_mask = sta->supp_rates[sband->band]; index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); if (sband->band == IEEE80211_BAND_5GHZ) @@ -811,8 +797,6 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, else sel->rate_idx = rs_sta->last_txrate_idx; - rcu_read_unlock(); - IWL_DEBUG_RATE("leave: %d\n", index); } @@ -829,114 +813,28 @@ static struct rate_control_ops rs_ops = { .free_sta = rs_free_sta, }; -int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct iwl3945_priv *priv = hw->priv; - struct iwl3945_rs_sta *rs_sta; - struct sta_info *sta; - unsigned long flags; - int count = 0, i; - u32 samples = 0, success = 0, good = 0; - unsigned long now = jiffies; - u32 max_time = 0; - - rcu_read_lock(); - - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { - if (sta) - IWL_DEBUG_RATE("leave - no private rate data!\n"); - else - IWL_DEBUG_RATE("leave - no station!\n"); - rcu_read_unlock(); - return sprintf(buf, "station %d not found\n", sta_id); - } - - rs_sta = (void *)sta->rate_ctrl_priv; - spin_lock_irqsave(&rs_sta->lock, flags); - i = IWL_RATE_54M_INDEX; - while (1) { - u64 mask; - int j; - - count += - sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2); - - mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1)); - for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1) - buf[count++] = - (rs_sta->win[i].data & mask) ? '1' : '0'; - - samples += rs_sta->win[i].counter; - good += rs_sta->win[i].success_counter; - success += rs_sta->win[i].success_counter * - iwl3945_rates[i].ieee; - - if (rs_sta->win[i].stamp) { - int delta = - jiffies_to_msecs(now - rs_sta->win[i].stamp); - - if (delta > max_time) - max_time = delta; - - count += sprintf(&buf[count], "%5dms\n", delta); - } else - buf[count++] = '\n'; - - j = iwl3945_get_prev_ieee_rate(i); - if (j == i) - break; - i = j; - } - spin_unlock_irqrestore(&rs_sta->lock, flags); - rcu_read_unlock(); - - /* Display the average rate of all samples taken. - * - * NOTE: We multiple # of samples by 2 since the IEEE measurement - * added from iwl3945_rates is actually 2X the rate */ - if (samples) - count += sprintf( - &buf[count], - "\nAverage rate is %3d.%02dMbs over last %4dms\n" - "%3d%% success (%d good packets over %d tries)\n", - success / (2 * samples), (success * 5 / samples) % 10, - max_time, good * 100 / samples, good, samples); - else - count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n"); - - return count; -} - void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) { struct iwl3945_priv *priv = hw->priv; s32 rssi = 0; unsigned long flags; - struct ieee80211_local *local = hw_to_local(hw); struct iwl3945_rs_sta *rs_sta; - struct sta_info *sta; + struct ieee80211_sta *sta; + struct iwl3945_sta_priv *psta; IWL_DEBUG_RATE("enter\n"); - if (!local->rate_ctrl->ops->name || - strcmp(local->rate_ctrl->ops->name, RS_NAME)) { - IWL_WARNING("iwl-3945-rs not selected as rate control algo!\n"); - IWL_DEBUG_RATE("leave - mac80211 picked the wrong RC algo.\n"); - return; - } - rcu_read_lock(); - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { + sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); + psta = (void *) sta->drv_priv; + if (!sta || !psta) { IWL_DEBUG_RATE("leave - no private rate data!\n"); rcu_read_unlock(); return; } - rs_sta = (void *)sta->rate_ctrl_priv; + rs_sta = psta->rs_sta; spin_lock_irqsave(&rs_sta->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index f085d330bdcf..98b17ae6ef24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -175,15 +175,6 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) return rate; } -/** - * iwl3945_fill_rs_info - Fill an output text buffer with the rate representation - * - * NOTE: This is provided as a quick mechanism for a user to visualize - * the performance of the rate control algorithm and is not meant to be - * parsed software. - */ -extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); - /** * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info * diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 2a4933b5fb64..bdd32475b99c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -73,6 +73,10 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; extern int iwl3945_param_hwcrypto; extern int iwl3945_param_queues_num; +struct iwl3945_sta_priv { + struct iwl3945_rs_sta *rs_sta; +}; + enum iwl3945_antenna { IWL_ANTENNA_DIVERSITY, IWL_ANTENNA_MAIN, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 8b57b390c8ba..93944de923ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -35,8 +35,6 @@ #include -#include "../net/mac80211/rate.h" - #include "iwl-dev.h" #include "iwl-sta.h" #include "iwl-core.h" @@ -169,9 +167,9 @@ struct iwl_lq_sta { }; static void rs_rate_scale_perform(struct iwl_priv *priv, - struct net_device *dev, struct ieee80211_hdr *hdr, - struct sta_info *sta); + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta); static void rs_fill_link_cmd(const struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, u32 rate_n_flags); @@ -357,20 +355,20 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct iwl_lq_sta *lq_data, u8 tid, - struct sta_info *sta) + struct ieee80211_sta *sta) { DECLARE_MAC_BUF(mac); if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", - print_mac(mac, sta->sta.addr), tid); - ieee80211_start_tx_ba_session(priv->hw, sta->sta.addr, tid); + print_mac(mac, sta->addr), tid); + ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); } } static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, struct iwl_lq_sta *lq_data, - struct sta_info *sta) + struct ieee80211_sta *sta) { if ((tid < TID_MAX_LOAD_COUNT)) rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); @@ -770,7 +768,8 @@ out: /* * mac80211 sends us Tx status */ -static void rs_tx_status(void *priv_rate, struct net_device *dev, +static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { int status; @@ -778,11 +777,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, int rs_index, index = 0; struct iwl_lq_sta *lq_sta; struct iwl_link_quality_cmd *table; - struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw *hw = local_to_hw(local); + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_rate_scale_data *window = NULL; struct iwl_rate_scale_data *search_win = NULL; @@ -808,15 +805,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, if (retries > 15) retries = 15; - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - - if (!sta || !sta->rate_ctrl_priv) - goto out; - - - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)priv_sta; if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && !lq_sta->ibss_sta_added) @@ -962,9 +951,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, } /* See if there's a better rate or modulation mode to try. */ - rs_rate_scale_perform(priv, dev, hdr, sta); + rs_rate_scale_perform(priv, hdr, sta, lq_sta); out: - rcu_read_unlock(); return; } @@ -1140,7 +1128,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, static int rs_switch_to_mimo2(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; @@ -1148,10 +1136,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, s8 is_green = lq_sta->is_green; if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || - !sta->sta.ht_info.ht_supported) + !sta->ht_info.ht_supported) return -1; - if (((sta->sta.ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) + if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) == WLAN_HT_CAP_SM_PS_STATIC) return -1; @@ -1208,7 +1196,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, static int rs_switch_to_siso(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; @@ -1216,7 +1204,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, s32 rate; if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || - !sta->sta.ht_info.ht_supported) + !sta->ht_info.ht_supported) return -1; IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); @@ -1268,7 +1256,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv, static int rs_move_legacy_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, + struct ieee80211_sta *sta, int index) { struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -1376,7 +1364,7 @@ out: static int rs_move_siso_to_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, int index) + struct ieee80211_sta *sta, int index) { u8 is_green = lq_sta->is_green; struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -1487,7 +1475,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, static int rs_move_mimo_to_other(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, int index) + struct ieee80211_sta *sta, int index) { s8 is_green = lq_sta->is_green; struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); @@ -1680,12 +1668,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) * Do rate scaling and search for new modulation mode. */ static void rs_rate_scale_perform(struct iwl_priv *priv, - struct net_device *dev, struct ieee80211_hdr *hdr, - struct sta_info *sta) + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hw *hw = local_to_hw(local); + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; int low = IWL_RATE_INVALID; int high = IWL_RATE_INVALID; @@ -1700,7 +1687,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, __le16 fc; u16 rate_mask; u8 update_lq = 0; - struct iwl_lq_sta *lq_sta; struct iwl_scale_tbl_info *tbl, *tbl1; u16 rate_scale_index_msk = 0; u32 rate; @@ -1721,11 +1707,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, return; } - if (!sta || !sta->rate_ctrl_priv) + if (!sta || !lq_sta) return; - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; - lq_sta->supp_rates = sta->sta.supp_rates[lq_sta->band]; + lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); @@ -2064,9 +2049,9 @@ out: static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, - struct sta_info *sta) + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta) { - struct iwl_lq_sta *lq_sta; struct iwl_scale_tbl_info *tbl; int rate_idx; int i; @@ -2075,10 +2060,9 @@ static void rs_initialize_lq(struct iwl_priv *priv, u8 active_tbl = 0; u8 valid_tx_ant; - if (!sta || !sta->rate_ctrl_priv) + if (!sta || !lq_sta) goto out; - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; i = lq_sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && @@ -2119,37 +2103,30 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; } -static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { int i; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_conf *conf = &local->hw.conf; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct sta_info *sta; __le16 fc; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl_lq_sta *lq_sta; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta || !sta->rate_ctrl_priv) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - goto out; + !sta || !priv_sta) { + sel->rate_idx = rate_lowest_index(sband, sta); + return; } - lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)priv_sta; i = lq_sta->last_txrate_idx; if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && @@ -2167,23 +2144,22 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, lq_sta->lq.sta_id = sta_id; lq_sta->lq.rs_table[0].rate_n_flags = 0; lq_sta->ibss_sta_added = 1; - rs_initialize_lq(priv, conf, sta); + rs_initialize_lq(priv, conf, sta, lq_sta); } } if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - goto out; + sel->rate_idx = rate_lowest_index(sband, sta); + return; } if (sband->band == IEEE80211_BAND_5GHZ) i -= IWL_FIRST_OFDM_RATE; sel->rate_idx = i; -out: - rcu_read_unlock(); } -static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) +static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, + gfp_t gfp) { struct iwl_lq_sta *lq_sta; struct iwl_priv *priv; @@ -2206,20 +2182,16 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) return lq_sta; } -static void rs_rate_init(void *priv_rate, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { int i, j; - struct ieee80211_conf *conf = &local->hw.conf; - struct ieee80211_supported_band *sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; + struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct ieee80211_conf *conf = &priv->hw->conf; struct iwl_lq_sta *lq_sta = priv_sta; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - lq_sta->flush_timer = 0; - lq_sta->supp_rates = sta->sta.supp_rates[sband->band]; + lq_sta->supp_rates = sta->supp_rates[sband->band]; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); @@ -2232,17 +2204,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->ibss_sta_added = 0; if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, sta->sta.addr); + u8 sta_id = iwl_find_station(priv, sta->addr); DECLARE_MAC_BUF(mac); /* for IBSS the call are from tasklet */ IWL_DEBUG_RATE("LQ: ADD station %s\n", - print_mac(mac, sta->sta.addr)); + print_mac(mac, sta->addr)); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_RATE("LQ: ADD station %s\n", - print_mac(mac, sta->sta.addr)); - sta_id = iwl_add_station_flags(priv, sta->sta.addr, + print_mac(mac, sta->addr)); + sta_id = iwl_add_station_flags(priv, sta->addr, 0, CMD_ASYNC, NULL); } if ((sta_id != IWL_INVALID_STATION)) { @@ -2256,11 +2228,11 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, /* Find highest tx rate supported by hardware and destination station */ lq_sta->last_txrate_idx = 3; for (i = 0; i < sband->n_bitrates; i++) - if (sta->sta.supp_rates[sband->band] & BIT(i)) + if (sta->supp_rates[sband->band] & BIT(i)) lq_sta->last_txrate_idx = i; /* For MODE_IEEE80211A, skip over cck rates in global rate table */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + if (sband->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_dup = 0; @@ -2301,7 +2273,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; lq_sta->drv = priv; - rs_initialize_lq(priv, conf, sta); + rs_initialize_lq(priv, conf, sta, lq_sta); } static void rs_fill_link_cmd(const struct iwl_priv *priv, @@ -2423,9 +2395,9 @@ static void rs_fill_link_cmd(const struct iwl_priv *priv, lq_cmd->agg_params.agg_time_limit = cpu_to_le16(4000); } -static void *rs_alloc(struct ieee80211_local *local) +static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - return local->hw.priv; + return hw->priv; } /* rate scale requires free function to be implemented */ static void rs_free(void *priv_rate) @@ -2446,12 +2418,12 @@ static void rs_clear(void *priv_rate) #endif /* CONFIG_IWLWIFI_DEBUG */ } -static void rs_free_sta(void *priv_rate, void *priv_sta) +static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, + void *priv_sta) { struct iwl_lq_sta *lq_sta = priv_sta; - struct iwl_priv *priv; + struct iwl_priv *priv = priv_r; - priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("enter\n"); kfree(lq_sta); IWL_DEBUG_RATE("leave\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 62b26befddc5..d15a2c997954 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7370,15 +7370,6 @@ static ssize_t show_temperature(struct device *d, static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); -static ssize_t show_rs_window(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct iwl3945_priv *priv = d->driver_data; - return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID); -} -static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); - static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { @@ -7840,7 +7831,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { #endif &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, - &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, @@ -7908,6 +7898,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e SET_IEEE80211_DEV(hw, &pdev->dev); hw->rate_control_algorithm = "iwl-3945-rs"; + hw->sta_data_size = sizeof(struct iwl3945_sta_priv); IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 003e4a03874e..f5f5b1ff1584 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1800,4 +1800,72 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr); + +/* Rate control API */ +/** + * struct rate_selection - rate information for/from rate control algorithms + * + * @rate_idx: selected transmission rate index + * @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used + * @probe_idx: rate for probing (or -1) + * @max_rate_idx: maximum rate index that can be used, this is + * input to the algorithm and will be enforced + */ +struct rate_selection { + s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx; +}; + +struct rate_control_ops { + struct module *module; + const char *name; + void *(*alloc)(struct ieee80211_hw *hw, struct dentry *debugfsdir); + void (*clear)(void *priv); + void (*free)(void *priv); + + void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); + void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta); + void (*free_sta)(void *priv, struct ieee80211_sta *sta, + void *priv_sta); + + void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb); + void (*get_rate)(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, + struct rate_selection *sel); + + void (*add_sta_debugfs)(void *priv, void *priv_sta, + struct dentry *dir); + void (*remove_sta_debugfs)(void *priv, void *priv_sta); +}; + +static inline int rate_supported(struct ieee80211_sta *sta, + enum ieee80211_band band, + int index) +{ + return (sta == NULL || sta->supp_rates[band] & BIT(index)); +} + +static inline s8 +rate_lowest_index(struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta) +{ + int i; + + for (i = 0; i < sband->n_bitrates; i++) + if (rate_supported(sta, sband->band, i)) + return i; + + /* warn when we cannot find a rate. */ + WARN_ON(1); + + return 0; +} + + +int ieee80211_rate_control_register(struct rate_control_ops *ops); +void ieee80211_rate_control_unregister(struct rate_control_ops *ops); + #endif /* MAC80211_H */ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 89a183c2327a..855126a3039d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -693,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, sta_apply_parameters(local, sta, params); - rate_control_rate_init(sta, local); + rate_control_rate_init(sta); rcu_read_lock(); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 0b25b0f46b1a..8025b294588b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -724,6 +724,8 @@ struct ieee80211_local { #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { + struct dentry *rcdir; + struct dentry *rcname; struct dentry *frequency; struct dentry *antenna_sel_tx; struct dentry *antenna_sel_rx; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 7d2d5a041e26..d608c44047c0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -542,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u16 frag, type; __le16 fc; + struct ieee80211_supported_band *sband; struct ieee80211_tx_status_rtap_hdr *rthdr; struct ieee80211_sub_if_data *sdata; struct net_device *prev_dev = NULL; @@ -588,7 +589,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) sta->tx_retry_count += info->status.retry_count; } - rate_control_tx_status(local->mdev, skb); + sband = local->hw.wiphy->bands[info->band]; + rate_control_tx_status(local, sband, sta, skb); } rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8611a8318c9c..109c3a7e63ad 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1323,7 +1323,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); } - rate_control_rate_init(sta, local); + rate_control_rate_init(sta); if (elems.wmm_param) { set_sta_flags(sta, WLAN_STA_WME); @@ -2342,7 +2342,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, sta->sta.supp_rates[band] = supp_rates | ieee80211_mandatory_rates(local, band); - rate_control_rate_init(sta, local); + rate_control_rate_init(sta); if (sta_info_insert(sta)) return NULL; diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0388c090dfe9..5d786720d935 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -12,6 +12,7 @@ #include #include "rate.h" #include "ieee80211_i.h" +#include "debugfs.h" struct rate_control_alg { struct list_head list; @@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) module_put(ops->module); } +#ifdef CONFIG_MAC80211_DEBUGFS +static ssize_t rcname_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct rate_control_ref *ref = file->private_data; + int len = strlen(ref->ops->name); + + return simple_read_from_buffer(userbuf, count, ppos, + ref->ops->name, len); +} + +static const struct file_operations rcname_ops = { + .read = rcname_read, + .open = mac80211_open_file_generic, +}; +#endif + struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local) { + struct dentry *debugfsdir = NULL; struct rate_control_ref *ref; ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); if (!ref) goto fail_ref; kref_init(&ref->kref); + ref->local = local; ref->ops = ieee80211_rate_control_ops_get(name); if (!ref->ops) goto fail_ops; - ref->priv = ref->ops->alloc(local); + +#ifdef CONFIG_MAC80211_DEBUGFS + debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); + local->debugfs.rcdir = debugfsdir; + local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, + ref, &rcname_ops); +#endif + + ref->priv = ref->ops->alloc(&local->hw, debugfsdir); if (!ref->priv) goto fail_priv; return ref; @@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref) ctrl_ref = container_of(kref, struct rate_control_ref, kref); ctrl_ref->ops->free(ctrl_ref->priv); + +#ifdef CONFIG_MAC80211_DEBUGFS + debugfs_remove(ctrl_ref->local->debugfs.rcname); + ctrl_ref->local->debugfs.rcname = NULL; + debugfs_remove(ctrl_ref->local->debugfs.rcdir); + ctrl_ref->local->debugfs.rcdir = NULL; +#endif + ieee80211_rate_control_ops_put(ctrl_ref->ops); kfree(ctrl_ref); } -void rate_control_get_rate(struct net_device *dev, +void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband, - struct sk_buff *skb, + struct sta_info *sta, struct sk_buff *skb, struct rate_selection *sel) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct rate_control_ref *ref = local->rate_ctrl; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct sta_info *sta; + struct rate_control_ref *ref = sdata->local->rate_ctrl; + void *priv_sta = NULL; + struct ieee80211_sta *ista = NULL; int i; - rcu_read_lock(); - sta = sta_info_get(local, hdr->addr1); - sel->rate_idx = -1; sel->nonerp_idx = -1; sel->probe_idx = -1; + sel->max_rate_idx = sdata->max_ratectrl_rateidx; + + if (sta) { + ista = &sta->sta; + priv_sta = sta->rate_ctrl_priv; + } + + if (sta && sdata->force_unicast_rateidx > -1) + sel->rate_idx = sdata->force_unicast_rateidx; + else + ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); - ref->ops->get_rate(ref->priv, dev, sband, skb, sel); + if (sdata->max_ratectrl_rateidx > -1 && + sel->rate_idx > sdata->max_ratectrl_rateidx) + sel->rate_idx = sdata->max_ratectrl_rateidx; BUG_ON(sel->rate_idx < 0); @@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev, if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) break; - if (rate_supported(sta, sband->band, i) && + if (rate_supported(ista, sband->band, i) && !(rate->flags & IEEE80211_RATE_ERP_G)) sel->nonerp_idx = i; } } - - rcu_read_unlock(); } struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5f18c27eb900..eb94e584d24e 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -19,77 +19,48 @@ #include "ieee80211_i.h" #include "sta_info.h" -/** - * struct rate_selection - rate selection for rate control algos - * @rate: selected transmission rate index - * @nonerp: Non-ERP rate to use instead if ERP cannot be used - * @probe: rate for probing (or -1) - * - */ -struct rate_selection { - s8 rate_idx, nonerp_idx, probe_idx; -}; - -struct rate_control_ops { - struct module *module; - const char *name; - void (*tx_status)(void *priv, struct net_device *dev, - struct sk_buff *skb); - void (*get_rate)(void *priv, struct net_device *dev, - struct ieee80211_supported_band *band, - struct sk_buff *skb, - struct rate_selection *sel); - void (*rate_init)(void *priv, void *priv_sta, - struct ieee80211_local *local, struct sta_info *sta); - void (*clear)(void *priv); - - void *(*alloc)(struct ieee80211_local *local); - void (*free)(void *priv); - void *(*alloc_sta)(void *priv, gfp_t gfp); - void (*free_sta)(void *priv, void *priv_sta); - - int (*add_attrs)(void *priv, struct kobject *kobj); - void (*remove_attrs)(void *priv, struct kobject *kobj); - void (*add_sta_debugfs)(void *priv, void *priv_sta, - struct dentry *dir); - void (*remove_sta_debugfs)(void *priv, void *priv_sta); -}; - struct rate_control_ref { + struct ieee80211_local *local; struct rate_control_ops *ops; void *priv; struct kref kref; }; -int ieee80211_rate_control_register(struct rate_control_ops *ops); -void ieee80211_rate_control_unregister(struct rate_control_ops *ops); - /* Get a reference to the rate control algorithm. If `name' is NULL, get the * first available algorithm. */ struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local); -void rate_control_get_rate(struct net_device *dev, +void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct ieee80211_supported_band *sband, - struct sk_buff *skb, + struct sta_info *sta, struct sk_buff *skb, struct rate_selection *sel); struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); void rate_control_put(struct rate_control_ref *ref); -static inline void rate_control_tx_status(struct net_device *dev, +static inline void rate_control_tx_status(struct ieee80211_local *local, + struct ieee80211_supported_band *sband, + struct sta_info *sta, struct sk_buff *skb) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct rate_control_ref *ref = local->rate_ctrl; + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; - ref->ops->tx_status(ref->priv, dev, skb); + ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); } -static inline void rate_control_rate_init(struct sta_info *sta, - struct ieee80211_local *local) +static inline void rate_control_rate_init(struct sta_info *sta) { + struct ieee80211_local *local = sta->sdata->local; struct rate_control_ref *ref = sta->rate_ctrl; - ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta); + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + ref->ops->rate_init(ref->priv, sband, ista, priv_sta); } @@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local) } static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, + struct ieee80211_sta *sta, gfp_t gfp) { - return ref->ops->alloc_sta(ref->priv, gfp); + return ref->ops->alloc_sta(ref->priv, sta, gfp); } -static inline void rate_control_free_sta(struct rate_control_ref *ref, - void *priv) +static inline void rate_control_free_sta(struct sta_info *sta) { - ref->ops->free_sta(ref->priv, priv); + struct rate_control_ref *ref = sta->rate_ctrl; + struct ieee80211_sta *ista = &sta->sta; + void *priv_sta = sta->rate_ctrl_priv; + + ref->ops->free_sta(ref->priv, ista, priv_sta); } static inline void rate_control_add_sta_debugfs(struct sta_info *sta) @@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) #endif } -static inline int rate_supported(struct sta_info *sta, - enum ieee80211_band band, - int index) -{ - return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); -} - -static inline s8 -rate_lowest_index(struct ieee80211_local *local, - struct ieee80211_supported_band *sband, - struct sta_info *sta) -{ - int i; - - for (i = 0; i < sband->n_bitrates; i++) - if (rate_supported(sta, sband->band, i)) - return i; - - /* warn when we cannot find a rate. */ - WARN_ON(1); - - return 0; -} - - /* functions for rate control related to a device */ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, const char *name); diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index ffafc5da572e..01d64d53f3b9 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h @@ -124,7 +124,6 @@ struct rc_pid_events_file_info { * struct rc_pid_debugfs_entries - tunable parameters * * Algorithm parameters, tunable via debugfs. - * @dir: the debugfs directory for a specific phy * @target: target percentage for failed frames * @sampling_period: error sampling interval in milliseconds * @coeff_p: absolute value of the proportional coefficient @@ -143,7 +142,6 @@ struct rc_pid_events_file_info { * ordering of rates) */ struct rc_pid_debugfs_entries { - struct dentry *dir; struct dentry *target; struct dentry *sampling_period; struct dentry *coeff_p; diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index bc1c4569caa1..86eb374e3b87 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -68,18 +68,14 @@ * exhibited a worse failed frames behaviour and we'll choose the highest rate * whose failed frames behaviour is not worse than the one of the original rate * target. While at it, check that the new rate is valid. */ -static void rate_control_pid_adjust_rate(struct ieee80211_local *local, - struct sta_info *sta, int adj, +static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct rc_pid_sta_info *spinfo, int adj, struct rc_pid_rateinfo *rinfo) { - struct ieee80211_sub_if_data *sdata; - struct ieee80211_supported_band *sband; int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; - struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; int cur = spinfo->txrate_idx; - sdata = sta->sdata; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; band = sband->band; n_bitrates = sband->n_bitrates; @@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) } static void rate_control_pid_sample(struct rc_pid_info *pinfo, - struct ieee80211_local *local, - struct sta_info *sta) + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct rc_pid_sta_info *spinfo) { - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; struct rc_pid_rateinfo *rinfo = pinfo->rinfo; - struct ieee80211_supported_band *sband; u32 pf; s32 err_avg; u32 err_prop; @@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, int adj, i, j, tmp; unsigned long period; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - spinfo = sta->rate_ctrl_priv; - /* In case nothing happened during the previous control interval, turn * the sharpening factor on. */ period = (HZ * pinfo->sampling_period + 500) / 1000; @@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, if (unlikely(spinfo->tx_num_xmit == 0)) pf = spinfo->last_pf; else { + /* XXX: BAD HACK!!! */ + struct sta_info *si = container_of(sta, struct sta_info, sta); + pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; - if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) - mesh_plink_broken(sta); + + if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) + mesh_plink_broken(si); pf <<= RC_PID_ARITH_SHIFT; - sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) + si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) >> RC_PID_ARITH_SHIFT; } @@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, /* Change rate. */ if (adj) - rate_control_pid_adjust_rate(local, sta, adj, rinfo); + rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); } -static void rate_control_pid_tx_status(void *priv, struct net_device *dev, +static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_sub_if_data *sdata; struct rc_pid_info *pinfo = priv; - struct sta_info *sta; - struct rc_pid_sta_info *spinfo; + struct rc_pid_sta_info *spinfo = priv_sta; unsigned long period; - struct ieee80211_supported_band *sband; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - if (!sta) - goto unlock; - - spinfo = sta->rate_ctrl_priv; - - /* Don't update the state if we're not controlling the rate. */ - sdata = sta->sdata; - if (sdata->force_unicast_rateidx > -1) { - spinfo->txrate_idx = sdata->max_ratectrl_rateidx; - goto unlock; - } + if (!spinfo) + return; /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ if (info->tx_rate_idx != spinfo->txrate_idx) - goto unlock; + return; spinfo->tx_num_xmit++; @@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, if (!period) period = 1; if (time_after(jiffies, spinfo->last_sample + period)) - rate_control_pid_sample(pinfo, local, sta); - - unlock: - rcu_read_unlock(); + rate_control_pid_sample(pinfo, sband, sta, spinfo); } -static void rate_control_pid_get_rate(void *priv, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void +rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, + struct rate_selection *sel) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_sub_if_data *sdata; - struct rc_pid_sta_info *spinfo; - struct sta_info *sta; + struct rc_pid_sta_info *spinfo = priv_sta; int rateidx; u16 fc; - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); - if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1) || !sta) { - sel->rate_idx = rate_lowest_index(local, sband, sta); - rcu_read_unlock(); + if (!sta || !spinfo || + (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || + is_multicast_ether_addr(hdr->addr1)) { + sel->rate_idx = rate_lowest_index(sband, sta); return; } - /* If a forced rate is in effect, select it. */ - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; - if (sdata->force_unicast_rateidx > -1) - spinfo->txrate_idx = sdata->force_unicast_rateidx; - rateidx = spinfo->txrate_idx; if (rateidx >= sband->n_bitrates) rateidx = sband->n_bitrates - 1; - rcu_read_unlock(); - sel->rate_idx = rateidx; #ifdef CONFIG_MAC80211_DEBUGFS - rate_control_pid_event_tx_rate( - &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, + rate_control_pid_event_tx_rate(&spinfo->events, rateidx, sband->bitrates[rateidx].bitrate); #endif } -static void rate_control_pid_rate_init(void *priv, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void +rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { + struct rc_pid_sta_info *spinfo = priv_sta; + struct sta_info *si; + /* TODO: This routine should consider using RSSI from previous packets * as we need to have IEEE 802.1X auth succeed immediately after assoc.. * Until that method is implemented, we will use the lowest supported * rate as a workaround. */ - struct ieee80211_supported_band *sband; - struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - spinfo->txrate_idx = rate_lowest_index(local, sband, sta); - sta->fail_avg = 0; + spinfo->txrate_idx = rate_lowest_index(sband, sta); + /* HACK */ + si = container_of(sta, struct sta_info, sta); + si->fail_avg = 0; } -static void *rate_control_pid_alloc(struct ieee80211_local *local) +static void *rate_control_pid_alloc(struct ieee80211_hw *hw, + struct dentry *debugfsdir) { struct rc_pid_info *pinfo; struct rc_pid_rateinfo *rinfo; @@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) struct rc_pid_debugfs_entries *de; #endif - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = hw->wiphy->bands[hw->conf.channel->band]; pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); if (!pinfo) @@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) #ifdef CONFIG_MAC80211_DEBUGFS de = &pinfo->dentries; - de->dir = debugfs_create_dir("rc80211_pid", - local->hw.wiphy->debugfsdir); de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, - de->dir, &pinfo->target); + debugfsdir, &pinfo->target); de->sampling_period = debugfs_create_u32("sampling_period", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->sampling_period); de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, - de->dir, &pinfo->coeff_p); + debugfsdir, &pinfo->coeff_p); de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, - de->dir, &pinfo->coeff_i); + debugfsdir, &pinfo->coeff_i); de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, - de->dir, &pinfo->coeff_d); + debugfsdir, &pinfo->coeff_d); de->smoothing_shift = debugfs_create_u32("smoothing_shift", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->smoothing_shift); de->sharpen_factor = debugfs_create_u32("sharpen_factor", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->sharpen_factor); de->sharpen_duration = debugfs_create_u32("sharpen_duration", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->sharpen_duration); de->norm_offset = debugfs_create_u32("norm_offset", - S_IRUSR | S_IWUSR, de->dir, + S_IRUSR | S_IWUSR, debugfsdir, &pinfo->norm_offset); #endif @@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv) debugfs_remove(de->coeff_p); debugfs_remove(de->sampling_period); debugfs_remove(de->target); - debugfs_remove(de->dir); #endif kfree(pinfo->rinfo); @@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv) { } -static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) +static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, + gfp_t gfp) { struct rc_pid_sta_info *spinfo; @@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) return spinfo; } -static void rate_control_pid_free_sta(void *priv, void *priv_sta) +static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { - struct rc_pid_sta_info *spinfo = priv_sta; - kfree(spinfo); + kfree(priv_sta); } static struct rate_control_ops mac80211_rcpid = { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d9774ac2e0f7..9b72d15bc8dc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -93,8 +93,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, } /* protected by RCU */ -static struct sta_info *__sta_info_find(struct ieee80211_local *local, - const u8 *addr) +struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) { struct sta_info *sta; @@ -107,12 +106,6 @@ static struct sta_info *__sta_info_find(struct ieee80211_local *local, return sta; } -struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) -{ - return __sta_info_find(local, addr); -} -EXPORT_SYMBOL(sta_info_get); - struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, struct net_device *dev) { @@ -146,7 +139,7 @@ static void __sta_info_free(struct ieee80211_local *local, { DECLARE_MAC_BUF(mbuf); - rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); + rate_control_free_sta(sta); rate_control_put(sta->rate_ctrl); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -244,7 +237,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->rate_ctrl = rate_control_get(local->rate_ctrl); sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, - gfp); + &sta->sta, gfp); if (!sta->rate_ctrl_priv) { rate_control_put(sta->rate_ctrl); kfree(sta); @@ -308,7 +301,7 @@ int sta_info_insert(struct sta_info *sta) spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (__sta_info_find(local, sta->sta.addr)) { + if (sta_info_get(local, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); err = -EEXIST; goto out_free; @@ -834,7 +827,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, const u8 *addr) { - struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); + struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); if (!sta) return NULL; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index daedfa9e1c63..c3f436964621 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -416,7 +416,7 @@ static inline u32 get_sta_flags(struct sta_info *sta) /* * Get a STA info, must have be under RCU read lock. */ -struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr); +struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); /* * Get STA info by index, BROKEN! */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 00d96e63dce9..0cc2e23f082c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -446,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) sband = tx->local->hw.wiphy->bands[tx->channel->band]; if (likely(tx->rate_idx < 0)) { - rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); + rate_control_get_rate(tx->sdata, sband, tx->sta, + tx->skb, &rsel); if (tx->sta) tx->sta->last_txrate_idx = rsel.rate_idx; tx->rate_idx = rsel.rate_idx; @@ -1955,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, skb->do_not_encrypt = 1; info->band = band; - rate_control_get_rate(local->mdev, sband, skb, &rsel); + rate_control_get_rate(sdata, sband, NULL, skb, &rsel); if (unlikely(rsel.rate_idx < 0)) { if (net_ratelimit()) { -- cgit v1.2.3 From 4dfe51e10047a60e82734860cec0d9f660b102fc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Sep 2008 05:10:34 +0200 Subject: mac80211: probe with correct SSID While associated, we should probe with the SSID we're associated to, not the scan SSID. Signed-off-by: Johannes Berg Acked-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 109c3a7e63ad..52a648133018 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -942,8 +942,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, disassoc = 1; } else ieee80211_send_probe_req(sdata, ifsta->bssid, - local->scan_ssid, - local->scan_ssid_len); + ifsta->ssid, + ifsta->ssid_len); ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; } else { ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; -- cgit v1.2.3 From 4492bea656b70dad6a9ae7b59b1430fa38ba3345 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 22 Sep 2008 17:10:10 +0300 Subject: mac80211: fix led behavior in IBSS This patch fixes the led behavior in IBSS. After we joined an IBSS cell we need to inform the led that we got associated. Although there is no 802.11 association in IBSS mode, the semantic of "There is a link" is relevant. This allows the led to blink in IBSS mode (at least this solves a bug for iwlwifi). Signed-off-by: Emmanuel Grumbach Reviewed-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 52a648133018..e859a0ab6162 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1452,6 +1452,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + ieee80211_led_assoc(local, true); + memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); -- cgit v1.2.3 From b4a4bf5d77c7d32098a7080f34a8857dd7fa466d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Sep 2008 13:34:54 +0200 Subject: mac80211: fixups for "make master iface not wireless" In "mac80211: make master iface not wireless" I accidentally forgot to include these changes ... leading to the expected BUG_ON errors. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/iface.c | 9 ++++----- net/mac80211/wme.c | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b5cd91e89712..8336fee68d3e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -58,8 +58,9 @@ static inline int identical_mac_addr_allowed(int type1, int type2) static int ieee80211_open(struct net_device *dev) { - struct ieee80211_sub_if_data *sdata, *nsdata; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_sub_if_data *nsdata; + struct ieee80211_local *local = sdata->local; struct sta_info *sta; struct ieee80211_if_init_conf conf; u32 changed = 0; @@ -67,8 +68,6 @@ static int ieee80211_open(struct net_device *dev) bool need_hw_reconfig = 0; u8 null_addr[ETH_ALEN] = {0}; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* fail early if user set an invalid address */ if (compare_ether_addr(dev->dev_addr, null_addr) && !is_valid_ether_addr(dev->dev_addr)) @@ -512,8 +511,8 @@ static int ieee80211_stop(struct net_device *dev) static void ieee80211_set_multicast_list(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int allmulti, promisc, sdata_allmulti, sdata_promisc; allmulti = !!(dev->flags & IFF_ALLMULTI); diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index c703f8b44e92..139b5f267b34 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -73,9 +73,8 @@ static int wme_downgrade_ac(struct sk_buff *skb) /* Indicate which queue to use. */ -static u16 classify80211(struct sk_buff *skb, struct net_device *dev) +static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; if (!ieee80211_is_data(hdr->frame_control)) { @@ -113,14 +112,15 @@ static u16 classify80211(struct sk_buff *skb, struct net_device *dev) u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) { + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct sta_info *sta; u16 queue; u8 tid; - queue = classify80211(skb, dev); + queue = classify80211(local, skb); if (unlikely(queue >= local->hw.queues)) queue = local->hw.queues - 1; -- cgit v1.2.3 From d88410a0b657c5ccebd1c120af1f14c5ca6a3d95 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Thu, 25 Sep 2008 20:45:01 +0300 Subject: mac80211: remove wme_tx_queue and wme_rx_queue from net/mac80211/sta_info.h This patch removes wme_tx_queue and wme_rx_queue from struct sta_info and from the debugfs sub-structure of struct sta_info in net/mac80211/sta_info.h, as they are useless and not used. Signed-off-by: Rami Rosen Signed-off-by: John W. Linville --- net/mac80211/sta_info.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index c3f436964621..a6b51862a89d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -189,7 +189,6 @@ struct sta_ampdu_mlme { * @last_qual: qual of last received frame from this STA * @last_noise: noise of last received frame from this STA * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) - * @wme_rx_queue: TBD * @tx_filtered_count: TBD * @tx_retry_failed: TBD * @tx_retry_count: TBD @@ -199,7 +198,6 @@ struct sta_ampdu_mlme { * @tx_fragments: number of transmitted MPDUs * @last_txrate_idx: Index of the last used transmit rate * @tid_seq: TBD - * @wme_tx_queue: TBD * @ampdu_mlme: TBD * @timer_to_tid: identity mapping to ID timers * @tid_to_tx_q: map tid to tx queue @@ -258,9 +256,6 @@ struct sta_info { int last_qual; int last_noise; __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; -#ifdef CONFIG_MAC80211_DEBUG_COUNTERS - unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; -#endif /* Updated from TX status path only, no locking requirements */ unsigned long tx_filtered_count; @@ -274,9 +269,6 @@ struct sta_info { unsigned long tx_fragments; unsigned int last_txrate_idx; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; -#ifdef CONFIG_MAC80211_DEBUG_COUNTERS - unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; -#endif /* * Aggregation information, locked with lock. @@ -307,10 +299,6 @@ struct sta_info { struct dentry *num_ps_buf_frames; struct dentry *inactive_ms; struct dentry *last_seq_ctrl; -#ifdef CONFIG_MAC80211_DEBUG_COUNTERS - struct dentry *wme_rx_queue; - struct dentry *wme_tx_queue; -#endif struct dentry *agg_status; } debugfs; #endif -- cgit v1.2.3 From b0dee5784dff3e2984510a7fe7a7e48109001f94 Mon Sep 17 00:00:00 2001 From: Davide Pesavento Date: Sat, 27 Sep 2008 17:29:12 +0200 Subject: Fix modpost failure when rx handlers are not inlined. When CONFIG_MAC80211_MESH=n and CONFIG_MAC80211_NOINLINE=y, gcc doesn't optimize out a call to ieee80211_rx_h_mesh_fwding, even if the previous comparison is always false in this case. This leads to the following errors during modpost: ERROR: "mpp_path_lookup" [net/mac80211/mac80211.ko] undefined! ERROR: "mpp_path_add" [net/mac80211/mac80211.ko] undefined! Fix by removing the possibility of uninlining ieee80211_rx_h_mesh_fwding rx handler. Signed-off-by: Davide Pesavento Signed-off-by: John W. Linville --- net/mac80211/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c489865761bc..77e7b014872b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1379,7 +1379,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) return RX_QUEUED; } -static ieee80211_rx_result debug_noinline +static ieee80211_rx_result ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) { struct ieee80211_hdr *hdr; -- cgit v1.2.3 From 74af025073461b9ebe82771e48a5b8596c3cf75c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Sep 2008 12:38:09 -0700 Subject: wireless: restore revert lost to merge damage Restore revert "mac80211: Use IWEVASSOCREQIE instead of IWEVCUSTOM", originally reverted in commit bf7394ccc13fe291d9258f01113b4c61214ddeae. Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e859a0ab6162..edc339d649c4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -650,20 +650,51 @@ static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { + char *buf; + size_t len; + int i; union iwreq_data wrqu; + if (!ifsta->assocreq_ies && !ifsta->assocresp_ies) + return; + + buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + + ifsta->assocresp_ies_len), GFP_KERNEL); + if (!buf) + return; + + len = sprintf(buf, "ASSOCINFO("); if (ifsta->assocreq_ies) { - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = ifsta->assocreq_ies_len; - wireless_send_event(sdata->dev, IWEVASSOCREQIE, &wrqu, - ifsta->assocreq_ies); + len += sprintf(buf + len, "ReqIEs="); + for (i = 0; i < ifsta->assocreq_ies_len; i++) { + len += sprintf(buf + len, "%02x", + ifsta->assocreq_ies[i]); + } } if (ifsta->assocresp_ies) { - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = ifsta->assocresp_ies_len; - wireless_send_event(sdata->dev, IWEVASSOCRESPIE, &wrqu, - ifsta->assocresp_ies); + if (ifsta->assocreq_ies) + len += sprintf(buf + len, " "); + len += sprintf(buf + len, "RespIEs="); + for (i = 0; i < ifsta->assocresp_ies_len; i++) { + len += sprintf(buf + len, "%02x", + ifsta->assocresp_ies[i]); + } } + len += sprintf(buf + len, ")"); + + if (len > IW_CUSTOM_MAX) { + len = sprintf(buf, "ASSOCRESPIE="); + for (i = 0; i < ifsta->assocresp_ies_len; i++) { + len += sprintf(buf + len, "%02x", + ifsta->assocresp_ies[i]); + } + } + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = len; + wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + + kfree(buf); } -- cgit v1.2.3 From 8ef9dad3f7c0bdae84cd57f2bc6d4f53421406a8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sat, 27 Sep 2008 22:58:18 +0300 Subject: mac80211: remove shadowed variables in ieee80211_master_start_xmit This patch removes doubly defined variables in ieee80211_master_start_xmit Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/tx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0cc2e23f082c..226ce77363d7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1255,8 +1255,7 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, return 0; } -int ieee80211_master_start_xmit(struct sk_buff *skb, - struct net_device *dev) +int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_master_priv *mpriv = netdev_priv(dev); struct ieee80211_local *local = mpriv->local; @@ -1308,8 +1307,6 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, } } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_local *local = osdata->local; - struct ieee80211_hdr *hdr; int hdrlen; u16 len_rthdr; -- cgit v1.2.3 From f74b6a5498049bab28419a03e4b31fcdbe7a900d Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Thu, 2 Oct 2008 16:48:22 +0300 Subject: mac80211: remove redundant check in ieee80211_master_start_xmit (net/mac80211/tx.c) - This patch (against the linux-wireless-next git tree) removes a redundant check in ieee80211_master_start_xmit (net/mac80211/tx.c) and adjust indentation in this method accordingly. In this method, there is no need to call again the ieee80211_is_data() method; this is checked immediately before, in the "if" command (we will not enter this block unless ieee80211_is_data() is true, so that the "and" (&&) condition in that "if" command will be fullfilled ). Signed-off-by: Rami Rosen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 226ce77363d7..d7153bbcdb2b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1295,16 +1295,14 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) if (ieee80211_vif_is_mesh(&osdata->vif) && ieee80211_is_data(hdr->frame_control)) { - if (ieee80211_is_data(hdr->frame_control)) { - if (is_multicast_ether_addr(hdr->addr3)) - memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); - else - if (mesh_nexthop_lookup(skb, osdata)) - return 0; - if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) - IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, - fwded_frames); - } + if (is_multicast_ether_addr(hdr->addr3)) + memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); + else + if (mesh_nexthop_lookup(skb, osdata)) + return 0; + if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) + IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, + fwded_frames); } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { struct ieee80211_sub_if_data *sdata; int hdrlen; -- cgit v1.2.3 From 76708dee382a69b2f9d0e50f413f99fefb2dc509 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 5 Oct 2008 18:02:48 +0200 Subject: mac80211: free up 2 bytes in skb->cb Free up 2 bytes in skb->cb to be used for multi-rate retry later. Move iv_len and icv_len initialization into key alloc. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 2 +- drivers/net/wireless/ath9k/xmit.c | 2 +- drivers/net/wireless/b43/xmit.c | 4 ++-- drivers/net/wireless/b43legacy/xmit.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00crypto.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00queue.c | 7 +++++-- include/net/mac80211.h | 4 ++-- net/mac80211/key.c | 14 ++++++++++++++ net/mac80211/wep.c | 3 --- net/mac80211/wpa.c | 6 ------ 10 files changed, 29 insertions(+), 21 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index c151588aa484..47be49acf55e 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1188,7 +1188,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) if (info->control.hw_key) { keyidx = info->control.hw_key->hw_key_idx; - pktlen += info->control.icv_len; + pktlen += info->control.hw_key->icv_len; } ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index bdcb9e1799ca..3a4757942b3f 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -237,7 +237,7 @@ static int ath_tx_prepare(struct ath_softc *sc, if (tx_info->control.hw_key) { txctl->keyix = tx_info->control.hw_key->hw_key_idx; - txctl->frmlen += tx_info->control.icv_len; + txctl->frmlen += tx_info->control.hw_key->icv_len; if (tx_info->control.hw_key->alg == ALG_WEP) txctl->keytype = ATH9K_KEY_TYPE_WEP; diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5e0b71c3ad02..e0749c0074cc 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -252,7 +252,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, } /* Hardware appends ICV. */ - plcp_fragment_len += info->control.icv_len; + plcp_fragment_len += info->control.hw_key->icv_len; key_idx = b43_kidx_to_fw(dev, key_idx); mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & @@ -260,7 +260,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & B43_TXH_MAC_KEYALG; wlhdr_len = ieee80211_hdrlen(fctl); - iv_len = min((size_t) info->control.iv_len, + iv_len = min((size_t) info->control.hw_key->iv_len, ARRAY_SIZE(txhdr->iv)); memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); } diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 6835064758fb..a894169411c5 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -243,7 +243,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, if (key->enabled) { /* Hardware appends ICV. */ - plcp_fragment_len += info->control.icv_len; + plcp_fragment_len += info->control.hw_key->icv_len; key_idx = b43legacy_kidx_to_fw(dev, key_idx); mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) & @@ -252,7 +252,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, B43legacy_TX4_MAC_KEYALG_SHIFT) & B43legacy_TX4_MAC_KEYALG; wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control); - iv_len = min((size_t)info->control.iv_len, + iv_len = min((size_t)info->control.hw_key->iv_len, ARRAY_SIZE(txhdr->iv)); memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); } else { diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index e1448cfa9444..5a858e5106c4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -56,10 +56,10 @@ unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info) * note that these lengths should only be added when * mac80211 does not generate it. */ - overhead += tx_info->control.icv_len; + overhead += key->icv_len; if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) - overhead += tx_info->control.iv_len; + overhead += key->iv_len; if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { if (key->alg == ALG_TKIP) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index b7f4fe8fba6e..1676ac484790 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -374,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct txentry_desc txdesc; struct skb_frame_desc *skbdesc; - unsigned int iv_len = IEEE80211_SKB_CB(skb)->control.iv_len; + unsigned int iv_len; if (unlikely(rt2x00queue_full(queue))) return -EINVAL; @@ -410,8 +410,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) * the frame so we can provide it to the driver seperately. */ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && - !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) + !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) && + (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) { + iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; rt2x00crypto_tx_remove_iv(skb, iv_len); + } /* * It could be possible that the queue was corrupted and this diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f5f5b1ff1584..feb3be81dfa6 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -337,8 +337,6 @@ struct ieee80211_tx_info { unsigned long jiffies; s8 rts_cts_rate_idx, alt_retry_rate_idx; u8 retry_limit; - u8 icv_len; - u8 iv_len; } control; struct { u64 ampdu_ack_map; @@ -635,6 +633,8 @@ enum ieee80211_key_flags { */ struct ieee80211_key_conf { enum ieee80211_key_alg alg; + u8 icv_len; + u8 iv_len; u8 hw_key_idx; u8 flags; s8 keyidx; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 57afcd38cd9e..a5b06fe71980 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -281,6 +281,20 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, key->conf.alg = alg; key->conf.keyidx = idx; key->conf.keylen = key_len; + switch (alg) { + case ALG_WEP: + key->conf.iv_len = WEP_IV_LEN; + key->conf.icv_len = WEP_ICV_LEN; + break; + case ALG_TKIP: + key->conf.iv_len = TKIP_IV_LEN; + key->conf.icv_len = TKIP_ICV_LEN; + break; + case ALG_CCMP: + key->conf.iv_len = CCMP_HDR_LEN; + key->conf.icv_len = CCMP_MIC_LEN; + break; + } memcpy(key->conf.key, key_data, key_len); INIT_LIST_HEAD(&key->list); INIT_LIST_HEAD(&key->todo); diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 376c84987e4f..f0e2d3ecb5c4 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -313,9 +313,6 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - info->control.iv_len = WEP_IV_LEN; - info->control.icv_len = WEP_ICV_LEN; - if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) return -1; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 37ae9a959f63..6db649480e8f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -152,9 +152,6 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) int len, tail; u8 *pos; - info->control.icv_len = TKIP_ICV_LEN; - info->control.iv_len = TKIP_IV_LEN; - if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { /* hwaccel - with no need for preallocated room for IV/ICV */ @@ -374,9 +371,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) u8 *pos, *pn; int i; - info->control.icv_len = CCMP_MIC_LEN; - info->control.iv_len = CCMP_HDR_LEN; - if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { /* hwaccel - with no need for preallocated room for CCMP " -- cgit v1.2.3 From 870abdf67170daa9f1022e55a35c469239fcc74c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 5 Oct 2008 18:04:24 +0200 Subject: mac80211: add multi-rate retry support This patch adjusts the rate control API to allow multi-rate retry if supported by the driver. The ieee80211_hw struct specifies how many alternate rate selections the driver supports. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + drivers/net/wireless/b43/xmit.c | 2 +- drivers/net/wireless/b43legacy/main.c | 1 + drivers/net/wireless/b43legacy/xmit.c | 2 +- drivers/net/wireless/rtl8180_dev.c | 5 +++-- include/net/mac80211.h | 29 +++++++++++++++++++++++++---- net/mac80211/tx.c | 13 +++++++------ 7 files changed, 39 insertions(+), 14 deletions(-) (limited to 'net/mac80211') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3bf74e236abc..14c44df584d0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4588,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_ADHOC); hw->queues = b43_modparam_qos ? 4 : 1; + hw->max_altrates = 1; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index e0749c0074cc..2fabcf8f0474 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -208,7 +208,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, txrate = ieee80211_get_tx_rate(dev->wl->hw, info); rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; rate_ofdm = b43_is_ofdm_rate(rate); - fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate; + fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate; rate_fb = fbrate->hw_value; rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 9fb1421cbec2..c66d57560e7c 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3710,6 +3710,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_ADHOC); hw->queues = 1; /* FIXME: hardware has more queues */ + hw->max_altrates = 1; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index a894169411c5..65e833781608 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -210,7 +210,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, rate = tx_rate->hw_value; rate_ofdm = b43legacy_is_ofdm_rate(rate); - rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate; + rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate; rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); txhdr->mac_frame_ctl = wlhdr->frame_control; diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index abcd641c54be..df7e78ee8a88 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -292,8 +292,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) entry->plcp_len = cpu_to_le16(plcp_len); entry->tx_buf = cpu_to_le32(mapping); entry->frame_len = cpu_to_le32(skb->len); - entry->flags2 = info->control.alt_retry_rate_idx >= 0 ? - ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0; + entry->flags2 = info->control.retries[0].rate_idx >= 0 ? + ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; entry->retry_limit = info->control.retry_limit; entry->flags = cpu_to_le32(tx_flags); __skb_queue_tail(&ring->queue, skb); @@ -855,6 +855,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, priv = dev->priv; priv->pdev = pdev; + dev->max_altrates = 1; SET_IEEE80211_DEV(dev, &pdev->dev); pci_set_drvdata(pdev, dev); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index feb3be81dfa6..5617a1613c91 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -292,6 +292,20 @@ enum mac80211_tx_control_flags { #define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) +/* maximum number of alternate rate retry stages */ +#define IEEE80211_TX_MAX_ALTRATE 3 + +/** + * struct ieee80211_tx_altrate - alternate rate selection/status + * + * @rate_idx: rate index to attempt to send with + * @limit: number of retries before fallback + */ +struct ieee80211_tx_altrate { + s8 rate_idx; + u8 limit; +}; + /** * struct ieee80211_tx_info - skb transmit information * @@ -335,12 +349,14 @@ struct ieee80211_tx_info { struct ieee80211_key_conf *hw_key; struct ieee80211_sta *sta; unsigned long jiffies; - s8 rts_cts_rate_idx, alt_retry_rate_idx; + s8 rts_cts_rate_idx; u8 retry_limit; + struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE]; } control; struct { u64 ampdu_ack_map; int ack_signal; + struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1]; u8 retry_count; bool excessive_retries; u8 ampdu_ack_len; @@ -828,6 +844,9 @@ enum ieee80211_hw_flags { * within &struct ieee80211_vif. * @sta_data_size: size (in bytes) of the drv_priv data area * within &struct ieee80211_sta. + * + * @max_altrates: maximum number of alternate rate retry stages + * @max_altrate_tries: maximum number of tries for each stage */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -844,6 +863,8 @@ struct ieee80211_hw { u16 ampdu_queues; u16 max_listen_interval; s8 max_signal; + u8 max_altrates; + u8 max_altrate_tries; }; struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); @@ -900,11 +921,11 @@ ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw, static inline struct ieee80211_rate * ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, - const struct ieee80211_tx_info *c) + const struct ieee80211_tx_info *c, int idx) { - if (c->control.alt_retry_rate_idx < 0) + if (c->control.retries[idx].rate_idx < 0) return NULL; - return &hw->wiphy->bands[c->band]->bitrates[c->control.alt_retry_rate_idx]; + return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx]; } /** diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d7153bbcdb2b..1460537faf33 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -454,15 +454,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) if (unlikely(rsel.probe_idx >= 0)) { info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; - info->control.alt_retry_rate_idx = tx->rate_idx; + info->control.retries[0].rate_idx = tx->rate_idx; + info->control.retries[0].limit = tx->local->hw.max_altrate_tries; tx->rate_idx = rsel.probe_idx; - } else - info->control.alt_retry_rate_idx = -1; + } else if (info->control.retries[0].limit == 0) + info->control.retries[0].rate_idx = -1; if (unlikely(tx->rate_idx < 0)) return TX_DROP; } else - info->control.alt_retry_rate_idx = -1; + info->control.retries[0].rate_idx = -1; if (tx->sdata->bss_conf.use_cts_prot && (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { @@ -521,7 +522,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) * frames. * TODO: The last fragment could still use multiple retry * rates. */ - info->control.alt_retry_rate_idx = -1; + info->control.retries[0].rate_idx = -1; } /* Use CTS protection for unicast frames sent using extended rates if @@ -551,7 +552,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) int idx; /* Do not use multiple retry rates when using RTS/CTS */ - info->control.alt_retry_rate_idx = -1; + info->control.retries[0].rate_idx = -1; /* Use min(data rate, max base rate) as CTS/RTS rate */ rate = &sband->bitrates[tx->rate_idx]; -- cgit v1.2.3 From cccf129f820e431d84690729254a32f1709328fb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 5 Oct 2008 18:07:45 +0200 Subject: mac80211: add the 'minstrel' rate control algorithm Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 13 + net/mac80211/Makefile | 4 + net/mac80211/main.c | 5 + net/mac80211/rate.h | 14 + net/mac80211/rc80211_minstrel.c | 583 ++++++++++++++++++++++++++++++++ net/mac80211/rc80211_minstrel.h | 85 +++++ net/mac80211/rc80211_minstrel_debugfs.c | 164 +++++++++ 7 files changed, 868 insertions(+) create mode 100644 net/mac80211/rc80211_minstrel.c create mode 100644 net/mac80211/rc80211_minstrel.h create mode 100644 net/mac80211/rc80211_minstrel_debugfs.c (limited to 'net/mac80211') diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 8427518e4f20..7f710a27e91c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -22,6 +22,11 @@ config MAC80211_RC_PID mac80211 that uses a PID controller to select the TX rate. +config MAC80211_RC_MINSTREL + bool "Minstrel" + ---help--- + This option enables the 'minstrel' TX rate control algorithm + choice prompt "Default rate control algorithm" default MAC80211_RC_DEFAULT_PID @@ -39,11 +44,19 @@ config MAC80211_RC_DEFAULT_PID default rate control algorithm. You should choose this unless you know what you are doing. +config MAC80211_RC_DEFAULT_MINSTREL + bool "Minstrel" + depends on MAC80211_RC_MINSTREL + ---help--- + Select Minstrel as the default rate control algorithm. + + endchoice config MAC80211_RC_DEFAULT string default "pid" if MAC80211_RC_DEFAULT_PID + default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL default "" endmenu diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 2dc8f2bff27b..31cfd1f89a72 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -41,4 +41,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ rc80211_pid-y := rc80211_pid_algo.o rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o +rc80211_minstrel-y := rc80211_minstrel.o +rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o + mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) +mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d608c44047c0..ae62ad40ad63 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1015,6 +1015,10 @@ static int __init ieee80211_init(void) BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); + ret = rc80211_minstrel_init(); + if (ret) + return ret; + ret = rc80211_pid_init(); if (ret) return ret; @@ -1027,6 +1031,7 @@ static int __init ieee80211_init(void) static void __exit ieee80211_exit(void) { rc80211_pid_exit(); + rc80211_minstrel_exit(); /* * For key todo, it'll be empty by now but the work diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index eb94e584d24e..d0092f847f82 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -125,4 +125,18 @@ static inline void rc80211_pid_exit(void) } #endif +#ifdef CONFIG_MAC80211_RC_MINSTREL +extern int rc80211_minstrel_init(void); +extern void rc80211_minstrel_exit(void); +#else +static inline int rc80211_minstrel_init(void) +{ + return 0; +} +static inline void rc80211_minstrel_exit(void) +{ +} +#endif + + #endif /* IEEE80211_RATE_H */ diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c new file mode 100644 index 000000000000..f6d69dab07a3 --- /dev/null +++ b/net/mac80211/rc80211_minstrel.c @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based on minstrel.c: + * Copyright (C) 2005-2007 Derek Smithies + * Sponsored by Indranet Technologies Ltd + * + * Based on sample.c: + * Copyright (c) 2005 John Bicket + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ +#include +#include +#include +#include +#include +#include +#include +#include "rate.h" +#include "rc80211_minstrel.h" + +#define SAMPLE_COLUMNS 10 +#define SAMPLE_TBL(_mi, _idx, _col) \ + _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] + +/* convert mac80211 rate index to local array index */ +static inline int +rix_to_ndx(struct minstrel_sta_info *mi, int rix) +{ + int i = rix; + for (i = rix; i >= 0; i--) + if (mi->r[i].rix == rix) + break; + WARN_ON(mi->r[i].rix != rix); + return i; +} + +static inline bool +use_low_rate(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u16 fc; + + fc = le16_to_cpu(hdr->frame_control); + + return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || + (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || + is_multicast_ether_addr(hdr->addr1)); +} + + +static void +minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) +{ + u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; + u32 max_prob = 0, index_max_prob = 0; + u32 usecs; + u32 p; + int i; + + mi->stats_update = jiffies; + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + + usecs = mr->perfect_tx_time; + if (!usecs) + usecs = 1000000; + + /* To avoid rounding issues, probabilities scale from 0 (0%) + * to 18000 (100%) */ + if (mr->attempts) { + p = (mr->success * 18000) / mr->attempts; + mr->succ_hist += mr->success; + mr->att_hist += mr->attempts; + mr->cur_prob = p; + p = ((p * (100 - mp->ewma_level)) + (mr->probability * + mp->ewma_level)) / 100; + mr->probability = p; + mr->cur_tp = p * (1000000 / usecs); + } + + mr->last_success = mr->success; + mr->last_attempts = mr->attempts; + mr->success = 0; + mr->attempts = 0; + + /* Sample less often below the 10% chance of success. + * Sample less often above the 95% chance of success. */ + if ((mr->probability > 17100) || (mr->probability < 1800)) { + mr->adjusted_retry_count = mr->retry_count >> 1; + if (mr->adjusted_retry_count > 2) + mr->adjusted_retry_count = 2; + } else { + mr->adjusted_retry_count = mr->retry_count; + } + if (!mr->adjusted_retry_count) + mr->adjusted_retry_count = 2; + } + + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + if (max_tp < mr->cur_tp) { + index_max_tp = i; + max_tp = mr->cur_tp; + } + if (max_prob < mr->probability) { + index_max_prob = i; + max_prob = mr->probability; + } + } + + max_tp = 0; + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + + if (i == index_max_tp) + continue; + + if (max_tp < mr->cur_tp) { + index_max_tp2 = i; + max_tp = mr->cur_tp; + } + } + mi->max_tp_rate = index_max_tp; + mi->max_tp_rate2 = index_max_tp2; + mi->max_prob_rate = index_max_prob; +} + +static void +minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb) +{ + struct minstrel_sta_info *mi = priv_sta; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_altrate *ar = info->status.retries; + struct minstrel_priv *mp = priv; + int i, ndx, tries; + int success = 0; + + if (!info->status.excessive_retries) + success = 1; + + if (!mp->has_mrr || (ar[0].rate_idx < 0)) { + ndx = rix_to_ndx(mi, info->tx_rate_idx); + tries = info->status.retry_count + 1; + mi->r[ndx].success += success; + mi->r[ndx].attempts += tries; + return; + } + + for (i = 0; i < 4; i++) { + if (ar[i].rate_idx < 0) + break; + + ndx = rix_to_ndx(mi, ar[i].rate_idx); + mi->r[ndx].attempts += ar[i].limit + 1; + + if ((i != 3) && (ar[i + 1].rate_idx < 0)) + mi->r[ndx].success += success; + } + + if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) + mi->sample_count++; + + if (mi->sample_deferred > 0) + mi->sample_deferred--; +} + + +static inline unsigned int +minstrel_get_retry_count(struct minstrel_rate *mr, + struct ieee80211_tx_info *info) +{ + unsigned int retry = mr->adjusted_retry_count; + + if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + retry = max(2U, min(mr->retry_count_rtscts, retry)); + else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + retry = max(2U, min(mr->retry_count_cts, retry)); + return retry; +} + + +static int +minstrel_get_next_sample(struct minstrel_sta_info *mi) +{ + unsigned int sample_ndx; + sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); + mi->sample_idx++; + if (mi->sample_idx > (mi->n_rates - 2)) { + mi->sample_idx = 0; + mi->sample_column++; + if (mi->sample_column >= SAMPLE_COLUMNS) + mi->sample_column = 0; + } + return sample_ndx; +} + +void +minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct minstrel_sta_info *mi = priv_sta; + struct minstrel_priv *mp = priv; + struct ieee80211_tx_altrate *ar = info->control.retries; + unsigned int ndx, sample_ndx = 0; + bool mrr; + bool sample_slower = false; + bool sample = false; + int i, delta; + int mrr_ndx[3]; + int sample_rate; + + if (!sta || !mi || use_low_rate(skb)) { + sel->rate_idx = rate_lowest_index(sband, sta); + return; + } + + mrr = mp->has_mrr; + + /* mac80211 does not allow mrr for RTS/CTS */ + if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || + (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + mrr = false; + + if (time_after(jiffies, mi->stats_update + (mp->update_interval * + HZ) / 1000)) + minstrel_update_stats(mp, mi); + + ndx = mi->max_tp_rate; + + if (mrr) + sample_rate = mp->lookaround_rate_mrr; + else + sample_rate = mp->lookaround_rate; + + mi->packet_count++; + delta = (mi->packet_count * sample_rate / 100) - + (mi->sample_count + mi->sample_deferred / 2); + + /* delta > 0: sampling required */ + if (delta > 0) { + if (mi->packet_count >= 10000) { + mi->sample_deferred = 0; + mi->sample_count = 0; + mi->packet_count = 0; + } else if (delta > mi->n_rates * 2) { + /* With multi-rate retry, not every planned sample + * attempt actually gets used, due to the way the retry + * chain is set up - [max_tp,sample,prob,lowest] for + * sample_rate < max_tp. + * + * If there's too much sampling backlog and the link + * starts getting worse, minstrel would start bursting + * out lots of sampling frames, which would result + * in a large throughput loss. */ + mi->sample_count += (delta - mi->n_rates * 2); + } + + sample_ndx = minstrel_get_next_sample(mi); + sample = true; + sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time > + mi->r[ndx].perfect_tx_time); + + if (!sample_slower) { + ndx = sample_ndx; + mi->sample_count++; + } else { + /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark + * packets that have the sampling rate deferred to the + * second MRR stage. Increase the sample counter only + * if the deferred sample rate was actually used. + * Use the sample_deferred counter to make sure that + * the sampling is not done in large bursts */ + info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; + mi->sample_deferred++; + } + } + sel->rate_idx = mi->r[ndx].rix; + info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info); + + if (!mrr) { + ar[0].rate_idx = mi->lowest_rix; + ar[0].limit = mp->max_retry; + ar[1].rate_idx = -1; + return; + } + + /* MRR setup */ + if (sample) { + if (sample_slower) + mrr_ndx[0] = sample_ndx; + else + mrr_ndx[0] = mi->max_tp_rate; + } else { + mrr_ndx[0] = mi->max_tp_rate2; + } + mrr_ndx[1] = mi->max_prob_rate; + mrr_ndx[2] = 0; + for (i = 0; i < 3; i++) { + ar[i].rate_idx = mi->r[mrr_ndx[i]].rix; + ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count; + } +} + + +static void +calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local, + struct minstrel_rate *d, struct ieee80211_rate *rate) +{ + int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); + + d->perfect_tx_time = ieee80211_frame_duration(local, 1200, + rate->bitrate, erp, 1); + d->ack_time = ieee80211_frame_duration(local, 10, + rate->bitrate, erp, 1); +} + +static void +init_sample_table(struct minstrel_sta_info *mi) +{ + unsigned int i, col, new_idx; + unsigned int n_srates = mi->n_rates - 1; + u8 rnd[8]; + + mi->sample_column = 0; + mi->sample_idx = 0; + memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); + + for (col = 0; col < SAMPLE_COLUMNS; col++) { + for (i = 0; i < n_srates; i++) { + get_random_bytes(rnd, sizeof(rnd)); + new_idx = (i + rnd[i & 7]) % n_srates; + + while (SAMPLE_TBL(mi, new_idx, col) != 0) + new_idx = (new_idx + 1) % n_srates; + + /* Don't sample the slowest rate (i.e. slowest base + * rate). We must presume that the slowest rate works + * fine, or else other management frames will also be + * failing and the link will break */ + SAMPLE_TBL(mi, new_idx, col) = i + 1; + } + } +} + +static void +minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) +{ + struct minstrel_sta_info *mi = priv_sta; + struct minstrel_priv *mp = priv; + struct minstrel_rate *mr_ctl; + unsigned int i, n = 0; + unsigned int t_slot = 9; /* FIXME: get real slot time */ + + mi->lowest_rix = rate_lowest_index(sband, sta); + mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)]; + mi->sp_ack_dur = mr_ctl->ack_time; + + for (i = 0; i < sband->n_bitrates; i++) { + struct minstrel_rate *mr = &mi->r[n]; + unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; + unsigned int tx_time_single; + unsigned int cw = mp->cw_min; + + if (!rate_supported(sta, sband->band, i)) + continue; + n++; + memset(mr, 0, sizeof(*mr)); + + mr->rix = i; + mr->bitrate = sband->bitrates[i].bitrate / 5; + calc_rate_durations(mi, hw_to_local(mp->hw), mr, + &sband->bitrates[i]); + + /* calculate maximum number of retransmissions before + * fallback (based on maximum segment size) */ + mr->retry_count = 1; + mr->retry_count_cts = 1; + mr->retry_count_rtscts = 1; + tx_time = mr->perfect_tx_time + mi->sp_ack_dur; + do { + /* add one retransmission */ + tx_time_single = mr->ack_time + mr->perfect_tx_time; + + /* contention window */ + tx_time_single += t_slot + min(cw, mp->cw_max); + cw = (cw + 1) << 1; + + tx_time += tx_time_single; + tx_time_cts += tx_time_single + mi->sp_ack_dur; + tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; + if ((tx_time_cts < mp->segment_size) && + (mr->retry_count_cts < mp->max_retry)) + mr->retry_count_cts++; + if ((tx_time_rtscts < mp->segment_size) && + (mr->retry_count_rtscts < mp->max_retry)) + mr->retry_count_rtscts++; + } while ((tx_time < mp->segment_size) && + (++mr->retry_count < mp->max_retry)); + mr->adjusted_retry_count = mr->retry_count; + } + + for (i = n; i < sband->n_bitrates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + mr->rix = -1; + } + + mi->n_rates = n; + mi->stats_update = jiffies; + + init_sample_table(mi); +} + +static void * +minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) +{ + struct ieee80211_supported_band *sband; + struct minstrel_sta_info *mi; + struct minstrel_priv *mp = priv; + struct ieee80211_hw *hw = mp->hw; + int max_rates = 0; + int i; + + mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); + if (!mi) + return NULL; + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + sband = hw->wiphy->bands[hw->conf.channel->band]; + if (sband->n_bitrates > max_rates) + max_rates = sband->n_bitrates; + } + + mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); + if (!mi->r) + goto error; + + mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); + if (!mi->sample_table) + goto error1; + + mi->stats_update = jiffies; + return mi; + +error1: + kfree(mi->r); +error: + kfree(mi); + return NULL; +} + +static void +minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) +{ + struct minstrel_sta_info *mi = priv_sta; + + kfree(mi->sample_table); + kfree(mi->r); + kfree(mi); +} + +static void +minstrel_clear(void *priv) +{ +} + +static void * +minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +{ + struct minstrel_priv *mp; + + mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); + if (!mp) + return NULL; + + /* contention window settings + * Just an approximation. Using the per-queue values would complicate + * the calculations and is probably unnecessary */ + mp->cw_min = 15; + mp->cw_max = 1023; + + /* number of packets (in %) to use for sampling other rates + * sample less often for non-mrr packets, because the overhead + * is much higher than with mrr */ + mp->lookaround_rate = 5; + mp->lookaround_rate_mrr = 10; + + /* moving average weight for EWMA */ + mp->ewma_level = 75; + + /* maximum time that the hw is allowed to stay in one MRR segment */ + mp->segment_size = 6000; + + if (hw->max_altrate_tries > 0) + mp->max_retry = hw->max_altrate_tries; + else + /* safe default, does not necessarily have to match hw properties */ + mp->max_retry = 7; + + if (hw->max_altrates >= 3) + mp->has_mrr = true; + + mp->hw = hw; + mp->update_interval = 100; + + return mp; +} + +static void +minstrel_free(void *priv) +{ + kfree(priv); +} + +static struct rate_control_ops mac80211_minstrel = { + .name = "minstrel", + .tx_status = minstrel_tx_status, + .get_rate = minstrel_get_rate, + .rate_init = minstrel_rate_init, + .clear = minstrel_clear, + .alloc = minstrel_alloc, + .free = minstrel_free, + .alloc_sta = minstrel_alloc_sta, + .free_sta = minstrel_free_sta, +#ifdef CONFIG_MAC80211_DEBUGFS + .add_sta_debugfs = minstrel_add_sta_debugfs, + .remove_sta_debugfs = minstrel_remove_sta_debugfs, +#endif +}; + +int __init +rc80211_minstrel_init(void) +{ + return ieee80211_rate_control_register(&mac80211_minstrel); +} + +void +rc80211_minstrel_exit(void) +{ + ieee80211_rate_control_unregister(&mac80211_minstrel); +} + diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h new file mode 100644 index 000000000000..9a90a6aee043 --- /dev/null +++ b/net/mac80211/rc80211_minstrel.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __RC_MINSTREL_H +#define __RC_MINSTREL_H + +struct minstrel_rate { + int bitrate; + int rix; + + unsigned int perfect_tx_time; + unsigned int ack_time; + + unsigned int retry_count; + unsigned int retry_count_cts; + unsigned int retry_count_rtscts; + unsigned int adjusted_retry_count; + + u32 success; + u32 attempts; + u32 last_attempts; + u32 last_success; + + /* parts per thousand */ + u32 cur_prob; + u32 probability; + + /* per-rate throughput */ + u32 cur_tp; + u32 throughput; + + u64 succ_hist; + u64 att_hist; +}; + +struct minstrel_sta_info { + unsigned long stats_update; + unsigned int sp_ack_dur; + unsigned int rate_avg; + + unsigned int lowest_rix; + + unsigned int max_tp_rate; + unsigned int max_tp_rate2; + unsigned int max_prob_rate; + unsigned int packet_count; + unsigned int sample_count; + int sample_deferred; + + unsigned int sample_idx; + unsigned int sample_column; + + int n_rates; + struct minstrel_rate *r; + + /* sampling table */ + u8 *sample_table; + +#ifdef CONFIG_MAC80211_DEBUGFS + struct dentry *dbg_stats; +#endif +}; + +struct minstrel_priv { + struct ieee80211_hw *hw; + bool has_mrr; + unsigned int cw_min; + unsigned int cw_max; + unsigned int max_retry; + unsigned int ewma_level; + unsigned int segment_size; + unsigned int update_interval; + unsigned int lookaround_rate; + unsigned int lookaround_rate_mrr; +}; + +void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); +void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); + +#endif diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c new file mode 100644 index 000000000000..0b024cd6b809 --- /dev/null +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based on minstrel.c: + * Copyright (C) 2005-2007 Derek Smithies + * Sponsored by Indranet Technologies Ltd + * + * Based on sample.c: + * Copyright (c) 2005 John Bicket + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ +#include +#include +#include +#include +#include +#include +#include "rc80211_minstrel.h" + +struct minstrel_stats_info { + struct minstrel_sta_info *mi; + char buf[4096]; + size_t len; +}; + +static int +minstrel_stats_open(struct inode *inode, struct file *file) +{ + struct minstrel_sta_info *mi = inode->i_private; + struct minstrel_stats_info *ms; + unsigned int i, tp, prob, eprob; + char *p; + + ms = kmalloc(sizeof(*ms), GFP_KERNEL); + if (!ms) + return -ENOMEM; + + file->private_data = ms; + p = ms->buf; + p += sprintf(p, "rate throughput ewma prob this prob " + "this succ/attempt success attempts\n"); + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + + *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; + *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; + *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; + p += sprintf(p, "%3u%s", mr->bitrate / 2, + (mr->bitrate & 1 ? ".5" : " ")); + + tp = ((mr->cur_tp * 96) / 18000) >> 10; + prob = mr->cur_prob / 18; + eprob = mr->probability / 18; + + p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " + "%3u(%3u) %8llu %8llu\n", + tp / 10, tp % 10, + eprob / 10, eprob % 10, + prob / 10, prob % 10, + mr->last_success, + mr->last_attempts, + mr->succ_hist, + mr->att_hist); + } + p += sprintf(p, "\nTotal packet count:: ideal %d " + "lookaround %d\n\n", + mi->packet_count - mi->sample_count, + mi->sample_count); + ms->len = p - ms->buf; + + return 0; +} + +static int +minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) +{ + struct minstrel_stats_info *ms; + char *src; + + ms = file->private_data; + src = ms->buf; + + len = min(len, ms->len); + if (len <= *o) + return 0; + + src += *o; + len -= *o; + *o += len; + + if (copy_to_user(buf, src, len)) + return -EFAULT; + + return len; +} + +static int +minstrel_stats_release(struct inode *inode, struct file *file) +{ + struct minstrel_stats_info *ms = file->private_data; + + kfree(ms); + + return 0; +} + +static struct file_operations minstrel_stat_fops = { + .owner = THIS_MODULE, + .open = minstrel_stats_open, + .read = minstrel_stats_read, + .release = minstrel_stats_release, +}; + +void +minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) +{ + struct minstrel_sta_info *mi = priv_sta; + + mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, + &minstrel_stat_fops); +} + +void +minstrel_remove_sta_debugfs(void *priv, void *priv_sta) +{ + struct minstrel_sta_info *mi = priv_sta; + + debugfs_remove(mi->dbg_stats); +} -- cgit v1.2.3 From ad788b5e079484aa1d48aa90a3ebd7d954d2e7db Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 1 Oct 2008 15:45:02 -0400 Subject: mac80211: avoid "Wireless Event too big" message for assoc response The association response IEs are sent to userland with an IWEVCUSTOM event, which unfortunately is limited to a little more than 100 bytes of IE information with the encoding used. Many APs send so much IE information that this message overflows. When the IWEVCUSTOM event is too large, the kernel doesn't send it to userland anyway -- better just not to send it. An attempt was made by Jouni Malinen to correct this issue by converting to use IWEVASSOCREQIE and IWEVASSOCRESPIE messages instead ("mac80211: Use IWEVASSOCREQIE instead of IWEVCUSTOM"). Unfortunately, that caused a problem due to 32-/64-bit interactions on some systems and was reverted after the 'userland ABI' rule was invoked. That leaves us with this option instead of a proper fix, at least until we move to a cfg80211-based solution. Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index edc339d649c4..49f86fa56bff 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -690,9 +690,11 @@ static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, } } - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = len; - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + if (len <= IW_CUSTOM_MAX) { + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = len; + wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); + } kfree(buf); } -- cgit v1.2.3 From bf94e17bc8d35fc339945a42990a2f2b5e9b5a40 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 12 Oct 2008 23:51:38 -0700 Subject: net/mac80211/rx.c: fix build error older versions of gcc do not recognize that ieee80211_rx_h_mesh_fwding() is unused when CONFIG_MAC80211_MESH is disabled: net/built-in.o: In function `ieee80211_rx_h_mesh_fwding': rx.c:(.text+0xd89af): undefined reference to `mpp_path_lookup' rx.c:(.text+0xd89c6): undefined reference to `mpp_path_add' as this code construct: if (ieee80211_vif_is_mesh(&sdata->vif)) CALL_RXH(ieee80211_rx_h_mesh_fwding); still causes ieee80211_rx_h_mesh_fwding() to be linked in. Protect these places with an #ifdef. commit b0dee578 ("Fix modpost failure when rx handlers are not inlined.") solved part of this problem - this patch is still needed. Signed-off-by: Ingo Molnar Signed-off-by: David S. Miller --- net/mac80211/rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 77e7b014872b..cf6b121e1bbf 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1379,6 +1379,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) return RX_QUEUED; } +#ifdef CONFIG_MAC80211_MESH static ieee80211_rx_result ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) { @@ -1453,7 +1454,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) else return RX_DROP_MONITOR; } - +#endif static ieee80211_rx_result debug_noinline ieee80211_rx_h_data(struct ieee80211_rx_data *rx) @@ -1780,8 +1781,10 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, /* must be after MMIC verify so header is counted in MPDU mic */ CALL_RXH(ieee80211_rx_h_remove_qos_control) CALL_RXH(ieee80211_rx_h_amsdu) +#ifdef CONFIG_MAC80211_MESH if (ieee80211_vif_is_mesh(&sdata->vif)) CALL_RXH(ieee80211_rx_h_mesh_fwding); +#endif CALL_RXH(ieee80211_rx_h_data) CALL_RXH(ieee80211_rx_h_ctrl) CALL_RXH(ieee80211_rx_h_action) -- cgit v1.2.3