summaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211.c')
-rw-r--r--net/mac80211/ieee80211.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index e0ee65a969b..6378850d858 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -216,6 +216,7 @@ static int ieee80211_open(struct net_device *dev)
res = local->ops->start(local_to_hw(local));
if (res)
return res;
+ ieee80211_hw_config(local);
}
switch (sdata->type) {
@@ -232,7 +233,6 @@ static int ieee80211_open(struct net_device *dev)
netif_tx_unlock_bh(local->mdev);
local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
- ieee80211_hw_config(local);
}
break;
case IEEE80211_IF_TYPE_STA:
@@ -267,6 +267,17 @@ static int ieee80211_open(struct net_device *dev)
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++;
netif_start_queue(dev);
@@ -284,6 +295,18 @@ static int ieee80211_stop(struct net_device *dev)
netif_stop_queue(dev);
+ /*
+ * 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);
/* down all dependent devices, that is VLANs */
@@ -311,8 +334,7 @@ static int ieee80211_stop(struct net_device *dev)
ieee80211_configure_filter(local);
netif_tx_unlock_bh(local->mdev);
- local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
- ieee80211_hw_config(local);
+ local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
}
break;
case IEEE80211_IF_TYPE_STA:
@@ -334,6 +356,11 @@ static int ieee80211_stop(struct net_device *dev)
cancel_delayed_work(&local->scan_work);
}
flush_workqueue(local->hw.workqueue);
+
+ 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 */
default:
conf.if_id = dev->ifindex;
@@ -366,8 +393,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
allmulti = !!(dev->flags & IFF_ALLMULTI);
promisc = !!(dev->flags & IFF_PROMISC);
- sdata_allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
- sdata_promisc = sdata->flags & IEEE80211_SDATA_PROMISC;
+ sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
+ sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
if (allmulti != sdata_allmulti) {
if (dev->flags & IFF_ALLMULTI)
@@ -400,7 +427,6 @@ static const struct header_ops ieee80211_header_ops = {
void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
- dev->header_ops = &ieee80211_header_ops;
dev->hard_start_xmit = ieee80211_subif_start_xmit;
dev->wireless_handlers = &ieee80211_iw_handler_def;
dev->set_multicast_list = ieee80211_set_multicast_list;