2012-04-17 00:08:41 +03:00
|
|
|
--- a/drivers/net/wireless/ath/ath5k/base.c
|
|
|
|
+++ b/drivers/net/wireless/ath/ath5k/base.c
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -2417,6 +2417,22 @@ ath5k_tx_complete_poll_work(struct work_
|
2012-04-17 00:08:41 +03:00
|
|
|
* Initialization routines *
|
|
|
|
\*************************/
|
|
|
|
|
|
|
|
+static const struct ieee80211_iface_limit if_limits[] = {
|
2012-04-17 03:05:41 +03:00
|
|
|
+ { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) },
|
|
|
|
+ { .max = 4, .types =
|
|
|
|
+#ifdef CONFIG_MAC80211_MESH
|
|
|
|
+ BIT(NL80211_IFTYPE_MESH_POINT) |
|
|
|
|
+#endif
|
|
|
|
+ BIT(NL80211_IFTYPE_AP) },
|
2012-04-17 00:08:41 +03:00
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct ieee80211_iface_combination if_comb = {
|
|
|
|
+ .limits = if_limits,
|
|
|
|
+ .n_limits = ARRAY_SIZE(if_limits),
|
2012-04-17 03:05:41 +03:00
|
|
|
+ .max_interfaces = 2048,
|
2012-04-17 00:08:41 +03:00
|
|
|
+ .num_different_channels = 1,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
int __devinit
|
|
|
|
ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
|
2012-03-10 14:59:24 +02:00
|
|
|
{
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -2438,6 +2454,9 @@ ath5k_init_ah(struct ath5k_hw *ah, const
|
2012-04-17 00:08:41 +03:00
|
|
|
BIT(NL80211_IFTYPE_ADHOC) |
|
|
|
|
BIT(NL80211_IFTYPE_MESH_POINT);
|
2012-03-10 14:59:24 +02:00
|
|
|
|
2012-04-17 00:08:41 +03:00
|
|
|
+ hw->wiphy->iface_combinations = &if_comb;
|
|
|
|
+ hw->wiphy->n_iface_combinations = 1;
|
|
|
|
+
|
|
|
|
/* SW support for IBSS_RSN is provided by mac80211 */
|
|
|
|
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
|
|
|
|
2011-06-01 02:07:29 +03:00
|
|
|
--- a/net/mac80211/agg-rx.c
|
|
|
|
+++ b/net/mac80211/agg-rx.c
|
2012-04-17 00:08:41 +03:00
|
|
|
@@ -200,6 +200,8 @@ static void ieee80211_send_addba_resp(st
|
2011-06-01 02:07:29 +03:00
|
|
|
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
|
2012-02-07 13:28:11 +02:00
|
|
|
else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
|
|
|
|
memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
|
2011-12-05 16:20:17 +02:00
|
|
|
+ else if (sdata->vif.type == NL80211_IFTYPE_WDS)
|
|
|
|
+ memcpy(mgmt->bssid, da, ETH_ALEN);
|
2011-06-01 02:07:29 +03:00
|
|
|
|
|
|
|
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
|
|
|
IEEE80211_STYPE_ACTION);
|
|
|
|
--- a/net/mac80211/agg-tx.c
|
|
|
|
+++ b/net/mac80211/agg-tx.c
|
2012-02-07 13:28:11 +02:00
|
|
|
@@ -81,7 +81,8 @@ static void ieee80211_send_addba_request
|
2011-06-01 02:07:29 +03:00
|
|
|
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
|
|
|
|
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
2011-11-18 13:27:19 +02:00
|
|
|
sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
|
|
|
|
- sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
|
|
|
|
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
|
2011-06-01 02:07:29 +03:00
|
|
|
+ sdata->vif.type == NL80211_IFTYPE_WDS)
|
|
|
|
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
|
|
|
|
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
|
|
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -490,6 +491,7 @@ int ieee80211_start_tx_ba_session(struct
|
2011-11-18 13:27:19 +02:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
|
2011-06-01 02:07:29 +03:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
2012-02-07 13:28:11 +02:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_AP &&
|
2011-12-05 16:20:17 +02:00
|
|
|
+ sdata->vif.type != NL80211_IFTYPE_WDS &&
|
2012-02-07 13:28:11 +02:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
2011-12-05 16:20:17 +02:00
|
|
|
return -EINVAL;
|
|
|
|
|
2011-06-01 02:07:29 +03:00
|
|
|
--- a/net/mac80211/debugfs_sta.c
|
|
|
|
+++ b/net/mac80211/debugfs_sta.c
|
2011-10-09 18:48:03 +03:00
|
|
|
@@ -63,11 +63,11 @@ static ssize_t sta_flags_read(struct fil
|
|
|
|
test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
|
|
|
|
|
|
|
|
int res = scnprintf(buf, sizeof(buf),
|
2012-04-17 00:08:41 +03:00
|
|
|
- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
|
|
|
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
2011-10-09 18:48:03 +03:00
|
|
|
TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
|
|
|
|
TEST(PS_DRIVER), TEST(AUTHORIZED),
|
2011-12-05 16:20:17 +02:00
|
|
|
TEST(SHORT_PREAMBLE),
|
2011-10-09 18:48:03 +03:00
|
|
|
- TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
|
|
|
|
+ TEST(WME), TEST(CLEAR_PS_FILT),
|
|
|
|
TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
|
|
|
|
TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
|
2012-02-07 13:28:11 +02:00
|
|
|
TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
|
2011-06-01 02:07:29 +03:00
|
|
|
--- a/net/mac80211/iface.c
|
|
|
|
+++ b/net/mac80211/iface.c
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -284,7 +284,6 @@ static int ieee80211_do_open(struct net_
|
2011-05-28 19:45:17 +03:00
|
|
|
{
|
2011-06-01 02:07:29 +03:00
|
|
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
- struct sta_info *sta;
|
|
|
|
u32 changed = 0;
|
|
|
|
int res;
|
|
|
|
u32 hw_reconf_flags = 0;
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -430,28 +429,6 @@ static int ieee80211_do_open(struct net_
|
2011-06-01 02:07:29 +03:00
|
|
|
|
|
|
|
set_bit(SDATA_STATE_RUNNING, &sdata->state);
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
- }
|
|
|
|
-
|
2012-02-07 13:28:11 +02:00
|
|
|
- sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
|
- sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
|
- sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
2011-06-01 02:07:29 +03:00
|
|
|
-
|
|
|
|
- res = sta_info_insert(sta);
|
|
|
|
- if (res) {
|
|
|
|
- /* STA has been freed */
|
|
|
|
- goto err_del_interface;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- rate_control_rate_init(sta);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/*
|
|
|
|
* set_multicast_list will be invoked by the networking core
|
|
|
|
* which will check whether any increments here were done in
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -848,6 +825,72 @@ static void ieee80211_if_setup(struct ne
|
2011-06-01 02:07:29 +03:00
|
|
|
dev->destructor = free_netdev;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|
|
|
+ struct sk_buff *skb)
|
|
|
|
+{
|
|
|
|
+ struct ieee80211_local *local = sdata->local;
|
|
|
|
+ struct ieee80211_rx_status *rx_status;
|
|
|
|
+ struct ieee802_11_elems elems;
|
|
|
|
+ struct ieee80211_mgmt *mgmt;
|
|
|
|
+ struct sta_info *sta;
|
|
|
|
+ size_t baselen;
|
|
|
|
+ u32 rates = 0;
|
|
|
|
+ u16 stype;
|
|
|
|
+ bool new = false;
|
|
|
|
+ enum ieee80211_band band = local->hw.conf.channel->band;
|
|
|
|
+ struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
|
|
|
|
+
|
|
|
|
+ rx_status = IEEE80211_SKB_RXCB(skb);
|
|
|
|
+ mgmt = (struct ieee80211_mgmt *) skb->data;
|
|
|
|
+ stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
|
|
|
|
+
|
|
|
|
+ if (stype != IEEE80211_STYPE_BEACON)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
|
|
|
|
+ if (baselen > skb->len)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
|
|
|
|
+ skb->len - baselen, &elems);
|
|
|
|
+
|
2012-04-17 00:08:41 +03:00
|
|
|
+ rates = ieee80211_sta_get_rates(local, &elems, band, NULL);
|
2011-06-01 02:07:29 +03:00
|
|
|
+
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+
|
|
|
|
+ sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
|
|
|
|
+
|
|
|
|
+ if (!sta) {
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!sta)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ new = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sta->last_rx = jiffies;
|
|
|
|
+ sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
|
|
|
|
+
|
|
|
|
+ if (elems.ht_cap_elem)
|
2011-12-05 16:20:17 +02:00
|
|
|
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
|
2011-06-01 02:07:29 +03:00
|
|
|
+ elems.ht_cap_elem, &sta->sta.ht_cap);
|
|
|
|
+
|
|
|
|
+ if (elems.wmm_param)
|
2011-10-09 18:48:03 +03:00
|
|
|
+ set_sta_flag(sta, WLAN_STA_WME);
|
2011-06-01 02:07:29 +03:00
|
|
|
+
|
|
|
|
+ if (new) {
|
2012-04-19 21:32:39 +03:00
|
|
|
+ sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
|
+ sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
|
+ sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
2011-06-01 02:07:29 +03:00
|
|
|
+ rate_control_rate_init(sta);
|
|
|
|
+ sta_info_insert_rcu(sta);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void ieee80211_iface_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct ieee80211_sub_if_data *sdata =
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -952,6 +995,9 @@ static void ieee80211_iface_work(struct
|
2011-06-01 02:07:29 +03:00
|
|
|
break;
|
|
|
|
ieee80211_mesh_rx_queued_mgmt(sdata, skb);
|
|
|
|
break;
|
|
|
|
+ case NL80211_IFTYPE_WDS:
|
|
|
|
+ ieee80211_wds_rx_queued_mgmt(sdata, skb);
|
|
|
|
+ break;
|
|
|
|
default:
|
|
|
|
WARN(1, "frame for unexpected interface type");
|
|
|
|
break;
|
|
|
|
--- a/net/mac80211/rx.c
|
|
|
|
+++ b/net/mac80211/rx.c
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -2284,6 +2284,7 @@ ieee80211_rx_h_action(struct ieee80211_r
|
2011-11-18 13:27:19 +02:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
|
2011-06-01 02:07:29 +03:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
2012-02-07 13:28:11 +02:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_AP &&
|
2011-12-05 16:20:17 +02:00
|
|
|
+ sdata->vif.type != NL80211_IFTYPE_WDS &&
|
2012-02-07 13:28:11 +02:00
|
|
|
sdata->vif.type != NL80211_IFTYPE_ADHOC)
|
2011-06-01 02:07:29 +03:00
|
|
|
break;
|
|
|
|
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -2498,14 +2499,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
|
2011-06-01 02:07:29 +03:00
|
|
|
|
|
|
|
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
|
|
|
|
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
|
|
|
|
- sdata->vif.type != NL80211_IFTYPE_STATION)
|
|
|
|
+ sdata->vif.type != NL80211_IFTYPE_STATION &&
|
|
|
|
+ sdata->vif.type != NL80211_IFTYPE_WDS)
|
|
|
|
return RX_DROP_MONITOR;
|
|
|
|
|
|
|
|
switch (stype) {
|
2012-02-07 13:28:11 +02:00
|
|
|
case cpu_to_le16(IEEE80211_STYPE_AUTH):
|
2011-06-01 02:07:29 +03:00
|
|
|
case cpu_to_le16(IEEE80211_STYPE_BEACON):
|
|
|
|
case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
|
|
|
|
- /* process for all: mesh, mlme, ibss */
|
|
|
|
+ /* process for all: mesh, mlme, ibss, wds */
|
|
|
|
break;
|
2012-02-07 13:28:11 +02:00
|
|
|
case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
|
|
|
|
case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
|
2012-05-30 04:01:06 +03:00
|
|
|
@@ -2839,10 +2841,16 @@ static int prepare_for_handlers(struct i
|
2011-06-01 02:07:29 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
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;
|
|
|
|
+
|
|
|
|
+ if (ieee80211_is_data(hdr->frame_control) ||
|
|
|
|
+ ieee80211_is_action(hdr->frame_control)) {
|
|
|
|
+ if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
|
|
|
|
+ return 0;
|
|
|
|
+ } else if (!ieee80211_is_beacon(hdr->frame_control))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* should never get here */
|
2012-02-28 00:56:05 +02:00
|
|
|
--- a/net/mac80211/sta_info.h
|
|
|
|
+++ b/net/mac80211/sta_info.h
|
2012-04-17 00:08:41 +03:00
|
|
|
@@ -32,7 +32,6 @@
|
2012-02-28 00:56:05 +02:00
|
|
|
* @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
|
|
|
|
* frames.
|
|
|
|
* @WLAN_STA_WME: Station is a QoS-STA.
|
|
|
|
- * @WLAN_STA_WDS: Station is one of our WDS peers.
|
|
|
|
* @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
|
|
|
|
* IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
|
|
|
|
* frame to this station is transmitted.
|
2012-04-17 00:08:41 +03:00
|
|
|
@@ -64,7 +63,6 @@ enum ieee80211_sta_info_flags {
|
2012-02-28 00:56:05 +02:00
|
|
|
WLAN_STA_AUTHORIZED,
|
|
|
|
WLAN_STA_SHORT_PREAMBLE,
|
|
|
|
WLAN_STA_WME,
|
|
|
|
- WLAN_STA_WDS,
|
|
|
|
WLAN_STA_CLEAR_PS_FILT,
|
|
|
|
WLAN_STA_MFP,
|
|
|
|
WLAN_STA_BLOCK_BA,
|