* [RFT 1/4] mac80211: make master netdev handling sane
2008-07-05 23:47 [RFT 0/4] mac80211 improvements Johannes Berg
@ 2008-07-05 23:47 ` Johannes Berg
2008-07-06 13:44 ` Kalle Valo
2008-07-08 10:42 ` Johannes Berg
2008-07-05 23:47 ` [RFT 2/4] mac80211: revamp virtual interface handling Johannes Berg
` (3 subsequent siblings)
4 siblings, 2 replies; 10+ messages in thread
From: Johannes Berg @ 2008-07-05 23:47 UTC (permalink / raw)
To: linux-wireless
Currently, almost every interface type has a 'bss' pointer
pointing to BSS information. This BSS information, however,
is for a _local_ BSS, not for the BSS we joined, so having
it on a STA mode interface makes little sense, but now they
have it pointing to the master device, which is an AP mode
virtual interface. However, except for some bitrate control
data, this pointer is only used in AP/VLAN modes (for power
saving stations.)
Overall, it is not necessary to even have the master netdev
be a valid virtual interface, and it doesn't have to be on
the list of interfaces either.
This patch changes the master netdev to be special, it now
- no longer is on the list of virtual interfaces, which
lets me remove a lot of tests for that
- no longer has sub_if_data attached, since that isn't used
Additionally, this patch changes some vlan/ap mode handling
that is related to these 'bss' pointers described above (but
in the VLAN case they actually make sense because there they
point to the AP they belong to); it also adds some debugging
code to IEEE80211_DEV_TO_SUB_IF to validate it is not called
on the master netdev any more.
******
** Please test!
**
** I have not tested this patch heavily yet, especially not
** in anything other than STA mode. I believe it should work
** with the possible exception of power saving in IBSS, but
** I don't think we handle that anyway because we don't do
** anything about ATIM windows etc.
******
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 2
net/mac80211/debugfs_netdev.c | 34 +++++++++++---
net/mac80211/ieee80211_i.h | 41 ++++++++++-------
net/mac80211/iface.c | 64 +++++---------------------
net/mac80211/main.c | 96 +++++++++++-----------------------------
net/mac80211/mlme.c | 56 +++++++----------------
net/mac80211/rc80211_pid_algo.c | 8 +--
net/mac80211/rx.c | 15 ++----
net/mac80211/sta_info.c | 29 ++++++++----
net/mac80211/tx.c | 11 ++--
net/mac80211/wext.c | 10 +---
11 files changed, 153 insertions(+), 213 deletions(-)
--- everything.orig/net/mac80211/ieee80211_i.h 2008-07-05 04:06:01.000000000 +0200
+++ everything/net/mac80211/ieee80211_i.h 2008-07-05 04:07:23.000000000 +0200
@@ -237,8 +237,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 force_unicast_rateidx; /* forced TX rateidx for unicast frames */
- int max_ratectrl_rateidx; /* max TX rateidx for rate control */
int num_beacons; /* number of TXed beacon frames for this BSS */
};
@@ -248,7 +246,6 @@ struct ieee80211_if_wds {
};
struct ieee80211_if_vlan {
- struct ieee80211_sub_if_data *ap;
struct list_head list;
};
@@ -432,16 +429,18 @@ struct ieee80211_sub_if_data {
struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
struct ieee80211_key *default_key;
+ /* BSS configuration for this interface. */
+ struct ieee80211_bss_conf bss_conf;
+
/*
- * BSS configuration for this interface.
- *
- * FIXME: I feel bad putting this here when we already have a
- * bss pointer, but the bss pointer is just wrong when
- * you have multiple virtual STA mode interfaces...
- * This needs to be fixed.
+ * AP this belongs to: self in AP mode and
+ * corresponding AP in VLAN mode, NULL for
+ * all others (might be needed later in IBSS)
*/
- struct ieee80211_bss_conf bss_conf;
- struct ieee80211_if_ap *bss; /* BSS that this device belongs to */
+ struct ieee80211_if_ap *bss;
+
+ int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+ int max_ratectrl_rateidx; /* max TX rateidx for rate control */
union {
struct ieee80211_if_ap ap;
@@ -533,8 +532,6 @@ struct ieee80211_sub_if_data *vif_to_sda
return container_of(p, struct ieee80211_sub_if_data, vif);
}
-#define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
-
enum {
IEEE80211_RX_MSG = 1,
IEEE80211_TX_STATUS_MSG = 2,
@@ -760,6 +757,16 @@ static inline int ieee80211_is_multiqueu
#endif
}
+static inline struct ieee80211_sub_if_data *
+IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+ BUG_ON(!local || local->mdev == dev);
+
+ return netdev_priv(dev);
+}
+
/* this struct represents 802.11n's RA/TID combination */
struct ieee80211_ra_tid {
u8 ra[ETH_ALEN];
@@ -882,8 +889,8 @@ int ieee80211_sta_scan_results(struct ne
ieee80211_rx_result ieee80211_sta_rx_scan(
struct net_device *dev, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status);
-void ieee80211_rx_bss_list_init(struct net_device *dev);
-void ieee80211_rx_bss_list_deinit(struct net_device *dev);
+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,
struct sk_buff *skb, u8 *bssid,
@@ -924,8 +931,8 @@ static inline void ieee80211_start_mesh(
{}
#endif
-/* ieee80211_iface.c */
-int ieee80211_if_add(struct net_device *dev, const char *name,
+/* interface handling */
+int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct net_device **new_dev, int type,
struct vif_params *params);
void ieee80211_if_set_type(struct net_device *dev, int type);
--- everything.orig/net/mac80211/iface.c 2008-07-05 04:05:58.000000000 +0200
+++ everything/net/mac80211/iface.c 2008-07-05 04:06:02.000000000 +0200
@@ -27,6 +27,9 @@ void ieee80211_if_sdata_init(struct ieee
skb_queue_head_init(&sdata->fragments[i].skb_list);
INIT_LIST_HEAD(&sdata->key_list);
+
+ sdata->force_unicast_rateidx = -1;
+ sdata->max_ratectrl_rateidx = -1;
}
static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
@@ -38,12 +41,11 @@ static void ieee80211_if_sdata_deinit(st
}
/* Must be called with rtnl lock held. */
-int ieee80211_if_add(struct net_device *dev, const char *name,
+int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct net_device **new_dev, int type,
struct vif_params *params)
{
struct net_device *ndev;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = NULL;
int ret;
@@ -67,13 +69,10 @@ int ieee80211_if_add(struct net_device *
goto fail;
memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
- ndev->base_addr = dev->base_addr;
- ndev->irq = dev->irq;
- ndev->mem_start = dev->mem_start;
- ndev->mem_end = dev->mem_end;
SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
- sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
+ /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
+ sdata = netdev_priv(ndev);
ndev->ieee80211_ptr = &sdata->wdev;
sdata->wdev.wiphy = local->hw.wiphy;
sdata->vif.type = IEEE80211_IF_TYPE_AP;
@@ -117,14 +116,6 @@ void ieee80211_if_set_type(struct net_de
int oldtype = sdata->vif.type;
/*
- * We need to call this function on the master interface
- * which already has a hard_start_xmit routine assigned
- * which must not be changed.
- */
- if (dev != sdata->local->mdev)
- dev->hard_start_xmit = ieee80211_subif_start_xmit;
-
- /*
* Called even when register_netdevice fails, it would
* oops if assigned before initialising the rest.
*/
@@ -138,22 +129,16 @@ void ieee80211_if_set_type(struct net_de
switch (type) {
case IEEE80211_IF_TYPE_WDS:
- /* nothing special */
- break;
case IEEE80211_IF_TYPE_VLAN:
- sdata->u.vlan.ap = NULL;
+ /* nothing special */
break;
case IEEE80211_IF_TYPE_AP:
- sdata->u.ap.force_unicast_rateidx = -1;
- sdata->u.ap.max_ratectrl_rateidx = -1;
skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
- sdata->bss = &sdata->u.ap;
INIT_LIST_HEAD(&sdata->u.ap.vlans);
break;
case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS: {
- struct ieee80211_sub_if_data *msdata;
struct ieee80211_if_sta *ifsta;
ifsta = &sdata->u.sta;
@@ -171,9 +156,6 @@ void ieee80211_if_set_type(struct net_de
if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
- msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
- sdata->bss = &msdata->u.ap;
-
if (ieee80211_vif_is_mesh(&sdata->vif))
ieee80211_mesh_init_sdata(sdata);
break;
@@ -215,27 +197,8 @@ void ieee80211_if_reinit(struct net_devi
WARN_ON(1);
break;
case IEEE80211_IF_TYPE_AP: {
- /* Remove all virtual interfaces that use this BSS
- * as their sdata->bss */
- struct ieee80211_sub_if_data *tsdata, *n;
struct beacon_data *beacon;
- list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
- if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
- printk(KERN_DEBUG "%s: removing virtual "
- "interface %s because its BSS interface"
- " is being removed\n",
- sdata->dev->name, tsdata->dev->name);
- list_del_rcu(&tsdata->list);
- /*
- * We have lots of time and can afford
- * to sync for each interface
- */
- synchronize_rcu();
- __ieee80211_if_del(local, tsdata);
- }
- }
-
beacon = sdata->u.ap.beacon;
rcu_assign_pointer(sdata->u.ap.beacon, NULL);
synchronize_rcu();
@@ -249,6 +212,7 @@ void ieee80211_if_reinit(struct net_devi
break;
}
case IEEE80211_IF_TYPE_WDS:
+ case IEEE80211_IF_TYPE_VLAN:
/* nothing to do */
break;
case IEEE80211_IF_TYPE_MESH_POINT:
@@ -269,9 +233,6 @@ void ieee80211_if_reinit(struct net_devi
case IEEE80211_IF_TYPE_MNTR:
dev->type = ARPHRD_ETHER;
break;
- case IEEE80211_IF_TYPE_VLAN:
- sdata->u.vlan.ap = NULL;
- break;
}
flushed = sta_info_flush(local, sdata);
@@ -289,8 +250,10 @@ void __ieee80211_if_del(struct ieee80211
ieee80211_debugfs_remove_netdev(sdata);
unregister_netdevice(dev);
- /* Except master interface, the net_device will be freed by
- * net_device->destructor (i. e. ieee80211_if_free). */
+ /*
+ * The net_device will be freed by its destructor,
+ * i.e. ieee80211_if_free.
+ */
}
/* Must be called with rtnl lock held. */
@@ -303,8 +266,7 @@ int ieee80211_if_remove(struct net_devic
list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
if ((sdata->vif.type == id || id == -1) &&
- strcmp(name, sdata->dev->name) == 0 &&
- sdata->dev != local->mdev) {
+ strcmp(name, sdata->dev->name) == 0) {
list_del_rcu(&sdata->list);
synchronize_rcu();
__ieee80211_if_del(local, sdata);
--- everything.orig/net/mac80211/main.c 2008-07-05 04:06:01.000000000 +0200
+++ everything/net/mac80211/main.c 2008-07-05 04:07:23.000000000 +0200
@@ -105,7 +105,7 @@ static int ieee80211_master_open(struct
/* we hold the RTNL here so can safely walk the list */
list_for_each_entry(sdata, &local->interfaces, list) {
- if (sdata->dev != dev && netif_running(sdata->dev)) {
+ if (netif_running(sdata->dev)) {
res = 0;
break;
}
@@ -126,7 +126,7 @@ static int ieee80211_master_stop(struct
/* we hold the RTNL here so can safely walk the list */
list_for_each_entry(sdata, &local->interfaces, list)
- if (sdata->dev != dev && netif_running(sdata->dev))
+ if (netif_running(sdata->dev))
dev_close(sdata->dev);
return 0;
@@ -193,7 +193,7 @@ static int ieee80211_open(struct net_dev
list_for_each_entry(nsdata, &local->interfaces, list) {
struct net_device *ndev = nsdata->dev;
- if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
+ if (ndev != dev && netif_running(ndev)) {
/*
* Allow only a single IBSS interface to be up at any
* time. This is restricted because beacon distribution
@@ -209,30 +209,6 @@ static int ieee80211_open(struct net_dev
return -EBUSY;
/*
- * Disallow multiple IBSS/STA mode interfaces.
- *
- * This is a technical restriction, it is possible although
- * most likely not IEEE 802.11 compliant to have multiple
- * STAs with just a single hardware (the TSF timer will not
- * be adjusted properly.)
- *
- * However, because mac80211 uses the master device's BSS
- * information for each STA/IBSS interface, doing this will
- * currently corrupt that BSS information completely, unless,
- * a not very useful case, both STAs are associated to the
- * same BSS.
- *
- * To remove this restriction, the BSS information needs to
- * be embedded in the STA/IBSS mode sdata instead of using
- * the master device's BSS structure.
- */
- if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
- (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
- nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
- return -EBUSY;
-
- /*
* The remaining checks are only performed for interfaces
* with the same MAC address.
*/
@@ -251,7 +227,7 @@ static int ieee80211_open(struct net_dev
*/
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
nsdata->vif.type == IEEE80211_IF_TYPE_AP)
- sdata->u.vlan.ap = nsdata;
+ sdata->bss = &nsdata->u.ap;
}
}
@@ -261,10 +237,13 @@ static int ieee80211_open(struct net_dev
return -ENOLINK;
break;
case IEEE80211_IF_TYPE_VLAN:
- if (!sdata->u.vlan.ap)
+ if (!sdata->bss)
return -ENOLINK;
+ list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
break;
case IEEE80211_IF_TYPE_AP:
+ sdata->bss = &sdata->u.ap;
+ break;
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_MNTR:
case IEEE80211_IF_TYPE_IBSS:
@@ -282,14 +261,13 @@ static int ieee80211_open(struct net_dev
if (local->ops->start)
res = local->ops->start(local_to_hw(local));
if (res)
- return res;
+ goto err_del_bss;
need_hw_reconfig = 1;
ieee80211_led_radio(local, local->hw.conf.radio_enabled);
}
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_VLAN:
- list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
/* no need to tell driver */
break;
case IEEE80211_IF_TYPE_MNTR:
@@ -402,6 +380,10 @@ static int ieee80211_open(struct net_dev
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 == IEEE80211_IF_TYPE_VLAN)
+ list_del(&sdata->u.vlan.list);
return res;
}
@@ -484,7 +466,6 @@ static int ieee80211_stop(struct net_dev
switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_VLAN:
list_del(&sdata->u.vlan.list);
- sdata->u.vlan.ap = NULL;
/* no need to tell driver */
break;
case IEEE80211_IF_TYPE_MNTR:
@@ -549,6 +530,8 @@ static int ieee80211_stop(struct net_dev
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);
@@ -1655,7 +1638,7 @@ int ieee80211_register_hw(struct ieee802
int result;
enum ieee80211_band band;
struct net_device *mdev;
- struct ieee80211_sub_if_data *sdata;
+ struct wireless_dev *mwdev;
/*
* generic code guarantees at least one band,
@@ -1695,8 +1678,7 @@ int ieee80211_register_hw(struct ieee802
hw->ampdu_queues = 0;
#endif
- /* for now, mdev needs sub_if_data :/ */
- mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data),
+ mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
"wmaster%d", ether_setup,
ieee80211_num_queues(hw));
if (!mdev)
@@ -1705,13 +1687,13 @@ int ieee80211_register_hw(struct ieee802
if (ieee80211_num_queues(hw) > 1)
mdev->features |= NETIF_F_MULTI_QUEUE;
- sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
- mdev->ieee80211_ptr = &sdata->wdev;
- sdata->wdev.wiphy = local->hw.wiphy;
+ mwdev = netdev_priv(mdev);
+ mdev->ieee80211_ptr = mwdev;
+ mwdev->wiphy = local->hw.wiphy;
local->mdev = mdev;
- ieee80211_rx_bss_list_init(mdev);
+ ieee80211_rx_bss_list_init(local);
mdev->hard_start_xmit = ieee80211_master_start_xmit;
mdev->open = ieee80211_master_open;
@@ -1720,16 +1702,6 @@ int ieee80211_register_hw(struct ieee802
mdev->header_ops = &ieee80211_header_ops;
mdev->set_multicast_list = ieee80211_master_set_multicast_list;
- sdata->vif.type = IEEE80211_IF_TYPE_AP;
- sdata->dev = mdev;
- sdata->local = local;
- sdata->u.ap.force_unicast_rateidx = -1;
- sdata->u.ap.max_ratectrl_rateidx = -1;
- ieee80211_if_sdata_init(sdata);
-
- /* no RCU needed since we're still during init phase */
- list_add_tail(&sdata->list, &local->interfaces);
-
name = wiphy_dev(local->hw.wiphy)->driver->name;
local->hw.workqueue = create_freezeable_workqueue(name);
if (!local->hw.workqueue) {
@@ -1775,9 +1747,6 @@ int ieee80211_register_hw(struct ieee802
if (result < 0)
goto fail_dev;
- ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
- ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
-
result = ieee80211_init_rate_ctrl_alg(local,
hw->rate_control_algorithm);
if (result < 0) {
@@ -1797,7 +1766,7 @@ int ieee80211_register_hw(struct ieee802
ieee80211_install_qdisc(local->mdev);
/* add one default STA interface */
- result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
+ result = ieee80211_if_add(local, "wlan%d", NULL,
IEEE80211_IF_TYPE_STA, NULL);
if (result)
printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
@@ -1813,7 +1782,6 @@ int ieee80211_register_hw(struct ieee802
fail_wep:
rate_control_deinitialize(local);
fail_rate:
- ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
unregister_netdevice(local->mdev);
local->mdev = NULL;
fail_dev:
@@ -1823,10 +1791,8 @@ fail_sta_info:
debugfs_hw_del(local);
destroy_workqueue(local->hw.workqueue);
fail_workqueue:
- if (local->mdev != NULL) {
- ieee80211_if_free(local->mdev);
- local->mdev = NULL;
- }
+ if (local->mdev)
+ free_netdev(local->mdev);
fail_mdev_alloc:
wiphy_unregister(local->hw.wiphy);
return result;
@@ -1854,24 +1820,19 @@ void ieee80211_unregister_hw(struct ieee
*/
/*
- * First, we remove all non-master interfaces. Do this because they
- * may have bss pointer dependency on the master, and when we free
- * the master these would be freed as well, breaking our list
- * iteration completely.
+ * First, we remove all virtual interfaces.
*/
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
- if (sdata->dev == local->mdev)
- continue;
list_del(&sdata->list);
__ieee80211_if_del(local, sdata);
}
/* then, finally, remove the master interface */
- __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
+ unregister_netdevice(local->mdev);
rtnl_unlock();
- ieee80211_rx_bss_list_deinit(local->mdev);
+ ieee80211_rx_bss_list_deinit(local);
ieee80211_clear_tx_pending(local);
sta_info_stop(local);
rate_control_deinitialize(local);
@@ -1888,8 +1849,7 @@ void ieee80211_unregister_hw(struct ieee
wiphy_unregister(local->hw.wiphy);
ieee80211_wep_free(local);
ieee80211_led_exit(local);
- ieee80211_if_free(local->mdev);
- local->mdev = NULL;
+ free_netdev(local->mdev);
}
EXPORT_SYMBOL(ieee80211_unregister_hw);
--- everything.orig/net/mac80211/rx.c 2008-07-05 04:06:00.000000000 +0200
+++ everything/net/mac80211/rx.c 2008-07-05 04:07:23.000000000 +0200
@@ -649,8 +649,7 @@ static void ap_sta_ps_start(struct net_d
sdata = sta->sdata;
- if (sdata->bss)
- atomic_inc(&sdata->bss->num_sta_ps);
+ 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",
@@ -669,8 +668,7 @@ static int ap_sta_ps_end(struct net_devi
sdata = sta->sdata;
- if (sdata->bss)
- atomic_dec(&sdata->bss->num_sta_ps);
+ atomic_dec(&sdata->bss->num_sta_ps);
clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
@@ -744,7 +742,9 @@ ieee80211_rx_h_sta_process(struct ieee80
sta->last_qual = rx->status->qual;
sta->last_noise = rx->status->noise;
- if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
+ if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS) &&
+ (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP ||
+ rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) {
/* Change STA power saving mode only in the end of a frame
* exchange sequence */
if (test_sta_flags(sta, WLAN_STA_PS) &&
@@ -1776,11 +1776,6 @@ static int prepare_for_handlers(struct i
return 0;
rx->flags &= ~IEEE80211_RX_RA_MATCH;
}
- if (sdata->dev == sdata->local->mdev &&
- !(rx->flags & IEEE80211_RX_IN_SCAN))
- /* do not receive anything via
- * master device when not scanning */
- return 0;
break;
case IEEE80211_IF_TYPE_WDS:
if (bssid ||
--- everything.orig/net/mac80211/sta_info.c 2008-07-05 04:05:59.000000000 +0200
+++ everything/net/mac80211/sta_info.c 2008-07-05 04:06:02.000000000 +0200
@@ -319,7 +319,9 @@ int sta_info_insert(struct sta_info *sta
/* notify driver */
if (local->ops->sta_notify) {
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
- sdata = sdata->u.vlan.ap;
+ sdata = container_of(sdata->bss,
+ struct ieee80211_sub_if_data,
+ u.ap);
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_ADD, sta->addr);
@@ -374,8 +376,10 @@ static inline void __bss_tim_clear(struc
static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
struct sta_info *sta)
{
- if (bss)
- __bss_tim_set(bss, sta->aid);
+ BUG_ON(!bss);
+
+ __bss_tim_set(bss, 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);
@@ -387,6 +391,8 @@ void sta_info_set_tim_bit(struct sta_inf
{
unsigned long flags;
+ BUG_ON(!sta->sdata->bss);
+
spin_lock_irqsave(&sta->local->sta_lock, flags);
__sta_info_set_tim_bit(sta->sdata->bss, sta);
spin_unlock_irqrestore(&sta->local->sta_lock, flags);
@@ -395,8 +401,10 @@ void sta_info_set_tim_bit(struct sta_inf
static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
struct sta_info *sta)
{
- if (bss)
- __bss_tim_clear(bss, sta->aid);
+ BUG_ON(!bss);
+
+ __bss_tim_clear(bss, 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);
@@ -408,6 +416,8 @@ void sta_info_clear_tim_bit(struct sta_i
{
unsigned long flags;
+ BUG_ON(!sta->sdata->bss);
+
spin_lock_irqsave(&sta->local->sta_lock, flags);
__sta_info_clear_tim_bit(sta->sdata->bss, sta);
spin_unlock_irqrestore(&sta->local->sta_lock, flags);
@@ -436,8 +446,9 @@ void __sta_info_unlink(struct sta_info *
list_del(&(*sta)->list);
if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) {
- if (sdata->bss)
- atomic_dec(&sdata->bss->num_sta_ps);
+ BUG_ON(!sdata->bss);
+
+ atomic_dec(&sdata->bss->num_sta_ps);
__sta_info_clear_tim_bit(sdata->bss, *sta);
}
@@ -445,7 +456,9 @@ void __sta_info_unlink(struct sta_info *
if (local->ops->sta_notify) {
if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
- sdata = sdata->u.vlan.ap;
+ sdata = container_of(sdata->bss,
+ struct ieee80211_sub_if_data,
+ u.ap);
local->ops->sta_notify(local_to_hw(local), &sdata->vif,
STA_NOTIFY_REMOVE, (*sta)->addr);
--- everything.orig/net/mac80211/tx.c 2008-07-05 04:05:59.000000000 +0200
+++ everything/net/mac80211/tx.c 2008-07-05 04:06:02.000000000 +0200
@@ -303,8 +303,7 @@ static void purge_old_ps_buffers(struct
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
struct ieee80211_if_ap *ap;
- if (sdata->dev == local->mdev ||
- sdata->vif.type != IEEE80211_IF_TYPE_AP)
+ if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
continue;
ap = &sdata->u.ap;
skb = skb_dequeue(&ap->ps_bc_buf);
@@ -346,8 +345,12 @@ ieee80211_tx_h_multicast_ps_buf(struct i
* This is done either by the hardware or us.
*/
- /* not AP/IBSS or ordered frame */
- if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER))
+ /* powersaving STAs only in AP/VLAN mode */
+ if (!tx->sdata->bss)
+ return TX_CONTINUE;
+
+ /* no buffering for ordered frames */
+ if (tx->fc & IEEE80211_FCTL_ORDER)
return TX_CONTINUE;
/* no stations in PS mode */
--- everything.orig/net/mac80211/wext.c 2008-07-05 04:05:58.000000000 +0200
+++ everything/net/mac80211/wext.c 2008-07-05 04:06:02.000000000 +0200
@@ -627,16 +627,14 @@ static int ieee80211_ioctl_siwrate(struc
struct ieee80211_supported_band *sband;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (!sdata->bss)
- return -ENODEV;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
/* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
* target_rate = X, rate->fixed = 1 means only rate X
* target_rate = X, rate->fixed = 0 means all rates <= X */
- sdata->bss->max_ratectrl_rateidx = -1;
- sdata->bss->force_unicast_rateidx = -1;
+ sdata->max_ratectrl_rateidx = -1;
+ sdata->force_unicast_rateidx = -1;
if (rate->value < 0)
return 0;
@@ -645,9 +643,9 @@ static int ieee80211_ioctl_siwrate(struc
int this_rate = brate->bitrate;
if (target_rate == this_rate) {
- sdata->bss->max_ratectrl_rateidx = i;
+ sdata->max_ratectrl_rateidx = i;
if (rate->fixed)
- sdata->bss->force_unicast_rateidx = i;
+ sdata->force_unicast_rateidx = i;
err = 0;
break;
}
--- everything.orig/net/mac80211/debugfs_netdev.c 2008-07-05 04:05:59.000000000 +0200
+++ everything/net/mac80211/debugfs_netdev.c 2008-07-05 04:06:02.000000000 +0200
@@ -156,6 +156,8 @@ static const struct file_operations name
/* common attributes */
IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
+IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
/* STA/IBSS attributes */
IEEE80211_IF_FILE(state, u.sta.state, DEC);
@@ -191,8 +193,6 @@ __IEEE80211_IF_FILE(flags);
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);
-IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
-IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
static ssize_t ieee80211_if_fmt_num_buffered_multicast(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -248,6 +248,9 @@ IEEE80211_IF_WFILE(min_discovery_timeout
static void add_sta_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(drop_unencrypted, sta);
+ DEBUGFS_ADD(force_unicast_rateidx, ap);
+ DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+
DEBUGFS_ADD(state, sta);
DEBUGFS_ADD(bssid, sta);
DEBUGFS_ADD(prev_bssid, sta);
@@ -268,23 +271,29 @@ static void add_sta_files(struct ieee802
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(drop_unencrypted, ap);
+ DEBUGFS_ADD(force_unicast_rateidx, ap);
+ DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+
DEBUGFS_ADD(num_sta_ps, ap);
DEBUGFS_ADD(dtim_count, ap);
DEBUGFS_ADD(num_beacons, ap);
- DEBUGFS_ADD(force_unicast_rateidx, ap);
- DEBUGFS_ADD(max_ratectrl_rateidx, ap);
DEBUGFS_ADD(num_buffered_multicast, ap);
}
static void add_wds_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(drop_unencrypted, wds);
+ DEBUGFS_ADD(force_unicast_rateidx, ap);
+ DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+
DEBUGFS_ADD(peer, wds);
}
static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(drop_unencrypted, vlan);
+ DEBUGFS_ADD(force_unicast_rateidx, ap);
+ DEBUGFS_ADD(max_ratectrl_rateidx, ap);
}
static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -372,6 +381,9 @@ static void add_files(struct ieee80211_s
static void del_sta_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(drop_unencrypted, sta);
+ DEBUGFS_DEL(force_unicast_rateidx, ap);
+ DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+
DEBUGFS_DEL(state, sta);
DEBUGFS_DEL(bssid, sta);
DEBUGFS_DEL(prev_bssid, sta);
@@ -392,23 +404,29 @@ static void del_sta_files(struct ieee802
static void del_ap_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(drop_unencrypted, ap);
+ DEBUGFS_DEL(force_unicast_rateidx, ap);
+ DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+
DEBUGFS_DEL(num_sta_ps, ap);
DEBUGFS_DEL(dtim_count, ap);
DEBUGFS_DEL(num_beacons, ap);
- DEBUGFS_DEL(force_unicast_rateidx, ap);
- DEBUGFS_DEL(max_ratectrl_rateidx, ap);
DEBUGFS_DEL(num_buffered_multicast, ap);
}
static void del_wds_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(drop_unencrypted, wds);
+ DEBUGFS_DEL(force_unicast_rateidx, ap);
+ DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+
DEBUGFS_DEL(peer, wds);
}
static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_DEL(drop_unencrypted, vlan);
+ DEBUGFS_DEL(force_unicast_rateidx, ap);
+ DEBUGFS_DEL(max_ratectrl_rateidx, ap);
}
static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -525,7 +543,7 @@ static int netdev_notify(struct notifier
{
struct net_device *dev = ndev;
struct dentry *dir;
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata;
char buf[10+IFNAMSIZ];
if (state != NETDEV_CHANGENAME)
@@ -537,6 +555,8 @@ static int netdev_notify(struct notifier
if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
return 0;
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
sprintf(buf, "netdev:%s", dev->name);
dir = sdata->debugfsdir;
if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
--- everything.orig/net/mac80211/rc80211_pid_algo.c 2008-07-05 04:05:59.000000000 +0200
+++ everything/net/mac80211/rc80211_pid_algo.c 2008-07-05 04:06:02.000000000 +0200
@@ -259,8 +259,8 @@ static void rate_control_pid_tx_status(v
/* Don't update the state if we're not controlling the rate. */
sdata = sta->sdata;
- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
- sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
+ if (sdata->force_unicast_rateidx > -1) {
+ sta->txrate_idx = sdata->max_ratectrl_rateidx;
goto unlock;
}
@@ -337,8 +337,8 @@ static void rate_control_pid_get_rate(vo
/* If a forced rate is in effect, select it. */
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
- sta->txrate_idx = sdata->bss->force_unicast_rateidx;
+ if (sdata->force_unicast_rateidx > -1)
+ sta->txrate_idx = sdata->force_unicast_rateidx;
rateidx = sta->txrate_idx;
--- everything.orig/net/mac80211/cfg.c 2008-07-05 04:05:59.000000000 +0200
+++ everything/net/mac80211/cfg.c 2008-07-05 04:06:02.000000000 +0200
@@ -57,7 +57,7 @@ static int ieee80211_add_iface(struct wi
if (itype == IEEE80211_IF_TYPE_INVALID)
return -EINVAL;
- err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
+ err = ieee80211_if_add(local, name, &dev, itype, params);
if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
return err;
--- everything.orig/net/mac80211/mlme.c 2008-07-05 04:05:59.000000000 +0200
+++ everything/net/mac80211/mlme.c 2008-07-05 04:06:02.000000000 +0200
@@ -78,7 +78,7 @@ static void ieee80211_send_probe_req(str
static struct ieee80211_sta_bss *
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
u8 *ssid, u8 ssid_len);
-static void ieee80211_rx_bss_put(struct net_device *dev,
+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,
struct ieee80211_if_sta *ifsta);
@@ -554,7 +554,7 @@ static void ieee80211_set_associated(str
changed |= ieee80211_handle_bss_capability(sdata, bss);
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
}
if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
@@ -757,7 +757,7 @@ static void ieee80211_send_assoc(struct
(local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
} else {
rates = ~0;
rates_len = sband->n_bitrates;
@@ -989,7 +989,7 @@ static int ieee80211_privacy_mismatch(st
wep_privacy = !!ieee80211_sta_wep_configured(dev);
privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
return 0;
@@ -2091,7 +2091,7 @@ static void ieee80211_rx_mgmt_assoc_resp
sta->last_signal = bss->signal;
sta->last_qual = bss->qual;
sta->last_noise = bss->noise;
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
}
err = sta_info_insert(sta);
@@ -2209,10 +2209,9 @@ static void __ieee80211_rx_bss_hash_add(
/* Caller must hold local->sta_bss_lock */
-static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
+static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *b, *prev = NULL;
b = local->sta_bss_hash[STA_HASH(bss->bssid)];
while (b) {
@@ -2364,39 +2363,35 @@ static void ieee80211_rx_bss_free(struct
}
-static void ieee80211_rx_bss_put(struct net_device *dev,
+static void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_sta_bss *bss)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
local_bh_disable();
if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
local_bh_enable();
return;
}
- __ieee80211_rx_bss_hash_del(dev, bss);
+ __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 net_device *dev)
+void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
spin_lock_init(&local->sta_bss_lock);
INIT_LIST_HEAD(&local->sta_bss_list);
}
-void ieee80211_rx_bss_list_deinit(struct net_device *dev)
+void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss, *tmp;
list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
}
@@ -2772,7 +2767,7 @@ static void ieee80211_rx_bss_info(struct
*/
if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
bss->probe_resp && beacon) {
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
return;
}
@@ -2915,7 +2910,7 @@ static void ieee80211_rx_bss_info(struct
}
}
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
}
@@ -3575,7 +3570,7 @@ static int ieee80211_sta_config_auth(str
selected->ssid_len);
ieee80211_sta_set_bssid(dev, selected->bssid);
ieee80211_sta_def_wmm_params(dev, selected, 0);
- ieee80211_rx_bss_put(dev, selected);
+ ieee80211_rx_bss_put(local, selected);
ifsta->state = IEEE80211_AUTHENTICATE;
ieee80211_sta_reset_auth(dev, ifsta);
return 0;
@@ -3652,7 +3647,7 @@ static int ieee80211_sta_create_ibss(str
}
ret = ieee80211_sta_join_ibss(dev, ifsta, bss);
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
return ret;
}
@@ -3706,7 +3701,7 @@ static int ieee80211_sta_find_ibss(struc
" based on configured SSID\n",
dev->name, print_mac(mac, bssid));
ret = ieee80211_sta_join_ibss(dev, ifsta, bss);
- ieee80211_rx_bss_put(dev, bss);
+ ieee80211_rx_bss_put(local, bss);
return ret;
}
#ifdef CONFIG_MAC80211_IBSS_DEBUG
@@ -3902,11 +3897,6 @@ void ieee80211_scan_completed(struct iee
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-
- /* No need to wake the master device. */
- if (sdata->dev == local->mdev)
- continue;
-
/* Tell AP we're back */
if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
@@ -4072,12 +4062,6 @@ static int ieee80211_sta_start_scan(stru
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-
- /* Don't stop the master interface, otherwise we can't transmit
- * probes! */
- if (sdata->dev == local->mdev)
- continue;
-
netif_stop_queue(sdata->dev);
if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
(sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
@@ -4468,12 +4452,10 @@ void ieee80211_notify_mac(struct ieee802
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)
+ continue;
- if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
- ieee80211_sta_req_auth(sdata->dev,
- &sdata->u.sta);
- }
-
+ ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta);
}
rcu_read_unlock();
break;
--
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFT 1/4] mac80211: make master netdev handling sane
2008-07-05 23:47 ` [RFT 1/4] mac80211: make master netdev handling sane Johannes Berg
@ 2008-07-06 13:44 ` Kalle Valo
2008-07-08 10:03 ` Johannes Berg
2008-07-08 10:42 ` Johannes Berg
1 sibling, 1 reply; 10+ messages in thread
From: Kalle Valo @ 2008-07-06 13:44 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
Johannes Berg <johannes@sipsolutions.net> writes:
> ******
> ** Please test!
> **
> ** I have not tested this patch heavily yet, especially not
> ** in anything other than STA mode. I believe it should work
> ** with the possible exception of power saving in IBSS, but
> ** I don't think we handle that anyway because we don't do
> ** anything about ATIM windows etc.
> ******
Are there any devices on the market which properly support PSM in
Ad-Hoc mode? At least N800/N810 don't support it.
I have heard that the standard is quite unclear regarding this. And,
after seeing the countless ways APs have managed to break PSM in
infrastructure mode, I can only imagine what kind of interoperability
problems there are with PSM in Ad-Hoc mode :)
So I think we should forget PSM in Ad-Hoc mode, at least for now.
--
Kalle Valo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFT 1/4] mac80211: make master netdev handling sane
2008-07-05 23:47 ` [RFT 1/4] mac80211: make master netdev handling sane Johannes Berg
2008-07-06 13:44 ` Kalle Valo
@ 2008-07-08 10:42 ` Johannes Berg
1 sibling, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2008-07-08 10:42 UTC (permalink / raw)
To: linux-wireless
[-- Attachment #1: Type: text/plain, Size: 1641 bytes --]
On Sun, 2008-07-06 at 01:47 +0200, Johannes Berg wrote:
> plain text document attachment (004-mac80211-master-not-ap.patch)
> Currently, almost every interface type has a 'bss' pointer
> pointing to BSS information. This BSS information, however,
> is for a _local_ BSS, not for the BSS we joined, so having
> it on a STA mode interface makes little sense, but now they
> have it pointing to the master device, which is an AP mode
> virtual interface. However, except for some bitrate control
> data, this pointer is only used in AP/VLAN modes (for power
> saving stations.)
>
> Overall, it is not necessary to even have the master netdev
> be a valid virtual interface, and it doesn't have to be on
> the list of interfaces either.
>
> This patch changes the master netdev to be special, it now
> - no longer is on the list of virtual interfaces, which
> lets me remove a lot of tests for that
> - no longer has sub_if_data attached, since that isn't used
>
> Additionally, this patch changes some vlan/ap mode handling
> that is related to these 'bss' pointers described above (but
> in the VLAN case they actually make sense because there they
> point to the AP they belong to); it also adds some debugging
> code to IEEE80211_DEV_TO_SUB_IF to validate it is not called
> on the master netdev any more.
> list_for_each_entry_rcu(sdata, &local->interfaces, list) {
> -
> - /* No need to wake the master device. */
> - if (sdata->dev == local->mdev)
> - continue;
> -
Just noticed that the patch was missing two hunks like that, I'll post
with them when I post this for good.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFT 2/4] mac80211: revamp virtual interface handling
2008-07-05 23:47 [RFT 0/4] mac80211 improvements Johannes Berg
2008-07-05 23:47 ` [RFT 1/4] mac80211: make master netdev handling sane Johannes Berg
@ 2008-07-05 23:47 ` Johannes Berg
2008-07-05 23:47 ` [RFT 3/4] mac80211: push interface checks down Johannes Berg
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2008-07-05 23:47 UTC (permalink / raw)
To: linux-wireless
This patch revamps the virtual interface handling and makes the
code much easier to follow. Fewer functions, better names, less
spaghetti code.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 24 --
net/mac80211/debugfs.c | 15 -
net/mac80211/debugfs_netdev.c | 14 -
net/mac80211/debugfs_netdev.h | 5
net/mac80211/ieee80211_i.h | 21 --
net/mac80211/iface.c | 337 +++++++++++++++++++-----------------------
net/mac80211/main.c | 18 --
net/mac80211/wext.c | 3
8 files changed, 172 insertions(+), 265 deletions(-)
--- everything.orig/net/mac80211/cfg.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/cfg.c 2008-07-05 23:33:16.000000000 +0200
@@ -50,9 +50,6 @@ static int ieee80211_add_iface(struct wi
struct ieee80211_sub_if_data *sdata;
int err;
- if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
- return -ENODEV;
-
itype = nl80211_type_to_mac80211_type(type);
if (itype == IEEE80211_IF_TYPE_INVALID)
return -EINVAL;
@@ -68,35 +65,26 @@ static int ieee80211_add_iface(struct wi
static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
{
- struct ieee80211_local *local = wiphy_priv(wiphy);
struct net_device *dev;
- char *name;
-
- if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
- return -ENODEV;
/* we're under RTNL */
dev = __dev_get_by_index(&init_net, ifindex);
if (!dev)
- return 0;
+ return -ENODEV;
- name = dev->name;
+ ieee80211_if_remove(dev);
- return ieee80211_if_remove(local->mdev, name, -1);
+ return 0;
}
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;
enum ieee80211_if_types itype;
struct ieee80211_sub_if_data *sdata;
- if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
- return -ENODEV;
-
/* we're under RTNL */
dev = __dev_get_by_index(&init_net, ifindex);
if (!dev)
@@ -111,11 +99,7 @@ static int ieee80211_change_iface(struct
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
- return -EOPNOTSUPP;
-
- ieee80211_if_reinit(dev);
- ieee80211_if_set_type(dev, itype);
+ ieee80211_if_change_type(sdata, itype);
if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
--- everything.orig/net/mac80211/ieee80211_i.h 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/ieee80211_i.h 2008-07-05 23:33:16.000000000 +0200
@@ -558,12 +558,6 @@ struct ieee80211_local {
bool tim_in_locked_section; /* see ieee80211_beacon_get() */
int tx_headroom; /* required headroom for hardware/radiotap */
- enum {
- IEEE80211_DEV_UNINITIALIZED = 0,
- IEEE80211_DEV_REGISTERED,
- IEEE80211_DEV_UNREGISTERED,
- } reg_state;
-
/* Tasklet and skb queue to process calls from IRQ mode. All frames
* added to skb_queue will be processed, but frames in
* skb_queue_unreliable may be dropped if the total length of these
@@ -863,7 +857,6 @@ int ieee80211_hw_config(struct ieee80211
int ieee80211_if_config(struct net_device *dev);
int ieee80211_if_config_beacon(struct net_device *dev);
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
-void ieee80211_if_setup(struct net_device *dev);
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);
@@ -932,16 +925,14 @@ static inline void ieee80211_start_mesh(
#endif
/* 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, int type,
+ struct net_device **new_dev, enum ieee80211_if_types type,
struct vif_params *params);
-void ieee80211_if_set_type(struct net_device *dev, int type);
-void ieee80211_if_reinit(struct net_device *dev);
-void __ieee80211_if_del(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata);
-int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
-void ieee80211_if_free(struct net_device *dev);
-void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+void 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_remove_interfaces(struct ieee80211_local *local);
/* tx handling */
void ieee80211_clear_tx_pending(struct ieee80211_local *local);
--- everything.orig/net/mac80211/iface.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/iface.c 2008-07-05 23:33:16.000000000 +0200
@@ -2,6 +2,7 @@
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
*
* 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
@@ -17,39 +18,149 @@
#include "debugfs_netdev.h"
#include "mesh.h"
-void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+/*
+ * Called when the netdev is removed or, by the code below, before
+ * the interface type changes.
+ */
+static void ieee80211_teardown_sdata(struct net_device *dev)
{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ struct beacon_data *beacon;
+ struct sk_buff *skb;
+ int flushed;
int i;
- /* Default values for sub-interface parameters */
- sdata->drop_unencrypted = 0;
+ ieee80211_debugfs_remove_netdev(sdata);
+
+ /* free extra data */
+ ieee80211_free_keys(sdata);
+
for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
- skb_queue_head_init(&sdata->fragments[i].skb_list);
+ __skb_queue_purge(&sdata->fragments[i].skb_list);
+ sdata->fragment_next = 0;
- INIT_LIST_HEAD(&sdata->key_list);
+ switch (sdata->vif.type) {
+ case IEEE80211_IF_TYPE_AP:
+ beacon = sdata->u.ap.beacon;
+ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+ synchronize_rcu();
+ kfree(beacon);
- sdata->force_unicast_rateidx = -1;
- sdata->max_ratectrl_rateidx = -1;
+ while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+ local->total_ps_buffered--;
+ dev_kfree_skb(skb);
+ }
+
+ 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(dev);
+ /* fall through */
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ 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:
+ break;
+ case IEEE80211_IF_TYPE_INVALID:
+ BUG();
+ break;
+ }
+
+ flushed = sta_info_flush(local, sdata);
+ WARN_ON(flushed);
}
-static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
+/*
+ * 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)
{
- int i;
+ struct ieee80211_if_sta *ifsta;
- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
- __skb_queue_purge(&sdata->fragments[i].skb_list);
+ /* clear type-dependent union */
+ memset(&sdata->u, 0, sizeof(sdata->u));
+
+ /* and set some type-dependent values */
+ sdata->vif.type = type;
+
+ /* only monitor differs */
+ sdata->dev->type = ARPHRD_ETHER;
+
+ switch (type) {
+ case IEEE80211_IF_TYPE_AP:
+ 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;
+ 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;
+
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ ieee80211_mesh_init_sdata(sdata);
+ break;
+ case IEEE80211_IF_TYPE_MNTR:
+ 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:
+ break;
+ case IEEE80211_IF_TYPE_INVALID:
+ BUG();
+ break;
+ }
+
+ ieee80211_debugfs_add_netdev(sdata);
+}
+
+void ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_if_types type)
+{
+ /* Purge and reset type-dependent state. */
+ ieee80211_teardown_sdata(sdata->dev);
+ ieee80211_setup_sdata(sdata, type);
+
+ /* reset some values that shouldn't be kept across type changes */
+ sdata->basic_rates = 0;
+ sdata->drop_unencrypted = 0;
+ sdata->sequence = 0;
}
-/* Must be called with rtnl lock held. */
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
- struct net_device **new_dev, int type,
+ struct net_device **new_dev, enum ieee80211_if_types type,
struct vif_params *params)
{
struct net_device *ndev;
struct ieee80211_sub_if_data *sdata = NULL;
- int ret;
+ int ret, i;
ASSERT_RTNL();
+
ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
name, ieee80211_if_setup);
if (!ndev)
@@ -74,18 +185,28 @@ int ieee80211_if_add(struct ieee80211_lo
/* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
sdata = netdev_priv(ndev);
ndev->ieee80211_ptr = &sdata->wdev;
+
+ /* initialise type-independent data */
sdata->wdev.wiphy = local->hw.wiphy;
- sdata->vif.type = IEEE80211_IF_TYPE_AP;
- sdata->dev = ndev;
sdata->local = local;
- ieee80211_if_sdata_init(sdata);
+ sdata->dev = ndev;
+
+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+ skb_queue_head_init(&sdata->fragments[i].skb_list);
+
+ INIT_LIST_HEAD(&sdata->key_list);
+
+ sdata->force_unicast_rateidx = -1;
+ sdata->max_ratectrl_rateidx = -1;
+
+ /* setup type-dependent data */
+ ieee80211_setup_sdata(sdata, type);
ret = register_netdevice(ndev);
if (ret)
goto fail;
- ieee80211_debugfs_add_netdev(sdata);
- ieee80211_if_set_type(ndev, type);
+ ndev->uninit = ieee80211_teardown_sdata;
if (ieee80211_vif_is_mesh(&sdata->vif) &&
params && params->mesh_id_len)
@@ -93,11 +214,6 @@ int ieee80211_if_add(struct ieee80211_lo
params->mesh_id_len,
params->mesh_id);
- /* we're under RTNL so all this is fine */
- if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
- __ieee80211_if_del(local, sdata);
- return -ENODEV;
- }
list_add_tail_rcu(&sdata->list, &local->interfaces);
if (new_dev)
@@ -105,181 +221,34 @@ int ieee80211_if_add(struct ieee80211_lo
return 0;
-fail:
+ fail:
free_netdev(ndev);
return ret;
}
-void ieee80211_if_set_type(struct net_device *dev, int type)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- int oldtype = sdata->vif.type;
-
- /*
- * Called even when register_netdevice fails, it would
- * oops if assigned before initialising the rest.
- */
- dev->uninit = ieee80211_if_reinit;
-
- /* most have no BSS pointer */
- sdata->bss = NULL;
- sdata->vif.type = type;
-
- sdata->basic_rates = 0;
-
- switch (type) {
- case IEEE80211_IF_TYPE_WDS:
- case IEEE80211_IF_TYPE_VLAN:
- /* nothing special */
- break;
- case IEEE80211_IF_TYPE_AP:
- 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: {
- struct ieee80211_if_sta *ifsta;
-
- 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;
-
- if (ieee80211_vif_is_mesh(&sdata->vif))
- ieee80211_mesh_init_sdata(sdata);
- break;
- }
- case IEEE80211_IF_TYPE_MNTR:
- dev->type = ARPHRD_IEEE80211_RADIOTAP;
- dev->hard_start_xmit = ieee80211_monitor_start_xmit;
- sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
- MONITOR_FLAG_OTHER_BSS;
- break;
- case IEEE80211_IF_TYPE_INVALID:
- BUG();
- break;
- }
- ieee80211_debugfs_change_if_type(sdata, oldtype);
-}
-
-/* Must be called with rtnl lock held. */
-void ieee80211_if_reinit(struct net_device *dev)
+void ieee80211_if_remove(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 sk_buff *skb;
- int flushed;
ASSERT_RTNL();
- ieee80211_free_keys(sdata);
-
- ieee80211_if_sdata_deinit(sdata);
-
- /* Need to handle mesh specially to allow eliding the function call */
- if (ieee80211_vif_is_mesh(&sdata->vif))
- mesh_rmc_free(dev);
-
- switch (sdata->vif.type) {
- case IEEE80211_IF_TYPE_INVALID:
- /* cannot happen */
- WARN_ON(1);
- break;
- case IEEE80211_IF_TYPE_AP: {
- struct beacon_data *beacon;
-
- beacon = sdata->u.ap.beacon;
- rcu_assign_pointer(sdata->u.ap.beacon, NULL);
- synchronize_rcu();
- kfree(beacon);
-
- while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
- local->total_ps_buffered--;
- dev_kfree_skb(skb);
- }
-
- break;
- }
- case IEEE80211_IF_TYPE_WDS:
- case IEEE80211_IF_TYPE_VLAN:
- /* nothing to do */
- break;
- case IEEE80211_IF_TYPE_MESH_POINT:
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
- kfree(sdata->u.sta.extra_ie);
- sdata->u.sta.extra_ie = NULL;
- kfree(sdata->u.sta.assocreq_ies);
- sdata->u.sta.assocreq_ies = NULL;
- kfree(sdata->u.sta.assocresp_ies);
- sdata->u.sta.assocresp_ies = NULL;
- if (sdata->u.sta.probe_resp) {
- dev_kfree_skb(sdata->u.sta.probe_resp);
- sdata->u.sta.probe_resp = NULL;
- }
-
- break;
- case IEEE80211_IF_TYPE_MNTR:
- dev->type = ARPHRD_ETHER;
- break;
- }
-
- flushed = sta_info_flush(local, sdata);
- WARN_ON(flushed);
-
- memset(&sdata->u, 0, sizeof(sdata->u));
- ieee80211_if_sdata_init(sdata);
-}
-
-/* Must be called with rtnl lock held. */
-void __ieee80211_if_del(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
-{
- struct net_device *dev = sdata->dev;
-
- ieee80211_debugfs_remove_netdev(sdata);
+ list_del_rcu(&sdata->list);
+ synchronize_rcu();
unregister_netdevice(dev);
- /*
- * The net_device will be freed by its destructor,
- * i.e. ieee80211_if_free.
- */
}
-/* Must be called with rtnl lock held. */
-int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+/*
+ * Remove all interfaces, may only be called at hardware unregistration
+ * time because it doesn't do RCU-safe list removals.
+ */
+void ieee80211_remove_interfaces(struct ieee80211_local *local)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_sub_if_data *sdata, *n;
+ struct ieee80211_sub_if_data *sdata, *tmp;
ASSERT_RTNL();
- list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
- if ((sdata->vif.type == id || id == -1) &&
- strcmp(name, sdata->dev->name) == 0) {
- list_del_rcu(&sdata->list);
- synchronize_rcu();
- __ieee80211_if_del(local, sdata);
- return 0;
- }
+ list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+ list_del(&sdata->list);
+ unregister_netdevice(sdata->dev);
}
- return -ENODEV;
-}
-
-void ieee80211_if_free(struct net_device *dev)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- ieee80211_if_sdata_deinit(sdata);
- free_netdev(dev);
}
--- everything.orig/net/mac80211/debugfs.c 2008-07-05 23:33:01.000000000 +0200
+++ everything/net/mac80211/debugfs.c 2008-07-05 23:33:16.000000000 +0200
@@ -70,16 +70,6 @@ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100
/* statistics stuff */
-static inline int rtnl_lock_local(struct ieee80211_local *local)
-{
- rtnl_lock();
- if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
- rtnl_unlock();
- return -ENODEV;
- }
- return 0;
-}
-
#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
@@ -96,10 +86,7 @@ static ssize_t format_devstat_counter(st
if (!local->ops->get_stats)
return -EOPNOTSUPP;
- res = rtnl_lock_local(local);
- if (res)
- return res;
-
+ rtnl_lock();
res = local->ops->get_stats(local_to_hw(local), &stats);
rtnl_unlock();
if (!res)
--- everything.orig/net/mac80211/main.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/main.c 2008-07-05 23:33:16.000000000 +0200
@@ -965,7 +965,6 @@ static const struct header_ops ieee80211
.cache_update = eth_header_cache_update,
};
-/* Must not be called for mdev */
void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -975,7 +974,7 @@ void ieee80211_if_setup(struct net_devic
dev->change_mtu = ieee80211_change_mtu;
dev->open = ieee80211_open;
dev->stop = ieee80211_stop;
- dev->destructor = ieee80211_if_free;
+ dev->destructor = free_netdev;
}
/* everything else */
@@ -1772,7 +1771,6 @@ int ieee80211_register_hw(struct ieee802
printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
wiphy_name(local->hw.wiphy));
- local->reg_state = IEEE80211_DEV_REGISTERED;
rtnl_unlock();
ieee80211_led_init(local);
@@ -1802,30 +1800,20 @@ EXPORT_SYMBOL(ieee80211_register_hw);
void ieee80211_unregister_hw(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata, *tmp;
tasklet_kill(&local->tx_pending_tasklet);
tasklet_kill(&local->tasklet);
rtnl_lock();
- BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
-
- local->reg_state = IEEE80211_DEV_UNREGISTERED;
-
/*
* At this point, interface list manipulations are fine
* because the driver cannot be handing us frames any
* more and the tasklet is killed.
*/
- /*
- * First, we remove all virtual interfaces.
- */
- list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
- list_del(&sdata->list);
- __ieee80211_if_del(local, sdata);
- }
+ /* First, we remove all virtual interfaces. */
+ ieee80211_remove_interfaces(local);
/* then, finally, remove the master interface */
unregister_netdevice(local->mdev);
--- everything.orig/net/mac80211/wext.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/wext.c 2008-07-05 23:33:16.000000000 +0200
@@ -301,8 +301,7 @@ static int ieee80211_ioctl_siwmode(struc
if (netif_running(dev))
return -EBUSY;
- ieee80211_if_reinit(dev);
- ieee80211_if_set_type(dev, type);
+ ieee80211_if_change_type(sdata, type);
return 0;
}
--- everything.orig/net/mac80211/debugfs_netdev.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/debugfs_netdev.c 2008-07-05 23:33:16.000000000 +0200
@@ -476,12 +476,12 @@ static void del_mesh_config(struct ieee8
}
#endif
-static void del_files(struct ieee80211_sub_if_data *sdata, int type)
+static void del_files(struct ieee80211_sub_if_data *sdata)
{
if (!sdata->debugfsdir)
return;
- switch (type) {
+ switch (sdata->vif.type) {
case IEEE80211_IF_TYPE_MESH_POINT:
#ifdef CONFIG_MAC80211_MESH
del_mesh_stats(sdata);
@@ -521,22 +521,16 @@ void ieee80211_debugfs_add_netdev(struct
sprintf(buf, "netdev:%s", sdata->dev->name);
sdata->debugfsdir = debugfs_create_dir(buf,
sdata->local->hw.wiphy->debugfsdir);
+ add_files(sdata);
}
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
{
- del_files(sdata, sdata->vif.type);
+ del_files(sdata);
debugfs_remove(sdata->debugfsdir);
sdata->debugfsdir = NULL;
}
-void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
- int oldtype)
-{
- del_files(sdata, oldtype);
- add_files(sdata);
-}
-
static int netdev_notify(struct notifier_block *nb,
unsigned long state,
void *ndev)
--- everything.orig/net/mac80211/debugfs_netdev.h 2008-07-05 23:33:01.000000000 +0200
+++ everything/net/mac80211/debugfs_netdev.h 2008-07-05 23:33:16.000000000 +0200
@@ -6,8 +6,6 @@
#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
-void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
- int oldtype);
void ieee80211_debugfs_netdev_init(void);
void ieee80211_debugfs_netdev_exit(void);
#else
@@ -17,9 +15,6 @@ static inline void ieee80211_debugfs_add
static inline void ieee80211_debugfs_remove_netdev(
struct ieee80211_sub_if_data *sdata)
{}
-static inline void ieee80211_debugfs_change_if_type(
- struct ieee80211_sub_if_data *sdata, int oldtype)
-{}
static inline void ieee80211_debugfs_netdev_init(void)
{}
--
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFT 3/4] mac80211: push interface checks down
2008-07-05 23:47 [RFT 0/4] mac80211 improvements Johannes Berg
2008-07-05 23:47 ` [RFT 1/4] mac80211: make master netdev handling sane Johannes Berg
2008-07-05 23:47 ` [RFT 2/4] mac80211: revamp virtual interface handling Johannes Berg
@ 2008-07-05 23:47 ` Johannes Berg
2008-07-05 23:47 ` [RFT 4/4] mac80211: revamp beacon configuration Johannes Berg
2008-07-08 11:53 ` [RFT 0/4] mac80211 improvements Ivo van Doorn
4 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2008-07-05 23:47 UTC (permalink / raw)
To: linux-wireless
This patch pushes the "netif_running()" and "same type as before"
checks down into ieee80211_if_change_type() to centralise the
logic instead of duplicating it for cfg80211 and wext.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
net/mac80211/cfg.c | 8 ++++----
net/mac80211/ieee80211_i.h | 4 ++--
net/mac80211/iface.c | 20 ++++++++++++++++++--
net/mac80211/wext.c | 9 +--------
4 files changed, 25 insertions(+), 16 deletions(-)
--- everything.orig/net/mac80211/cfg.c 2008-07-05 23:33:16.000000000 +0200
+++ everything/net/mac80211/cfg.c 2008-07-05 23:33:18.000000000 +0200
@@ -84,22 +84,22 @@ static int ieee80211_change_iface(struct
struct net_device *dev;
enum ieee80211_if_types itype;
struct ieee80211_sub_if_data *sdata;
+ int ret;
/* we're under RTNL */
dev = __dev_get_by_index(&init_net, ifindex);
if (!dev)
return -ENODEV;
- if (netif_running(dev))
- return -EBUSY;
-
itype = nl80211_type_to_mac80211_type(type);
if (itype == IEEE80211_IF_TYPE_INVALID)
return -EINVAL;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- ieee80211_if_change_type(sdata, itype);
+ ret = ieee80211_if_change_type(sdata, itype);
+ if (ret)
+ return ret;
if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
--- everything.orig/net/mac80211/ieee80211_i.h 2008-07-05 23:33:16.000000000 +0200
+++ everything/net/mac80211/ieee80211_i.h 2008-07-05 23:33:18.000000000 +0200
@@ -929,8 +929,8 @@ void ieee80211_if_setup(struct net_devic
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct net_device **new_dev, enum ieee80211_if_types type,
struct vif_params *params);
-void ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_if_types type);
+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_remove_interfaces(struct ieee80211_local *local);
--- everything.orig/net/mac80211/iface.c 2008-07-05 23:33:16.000000000 +0200
+++ everything/net/mac80211/iface.c 2008-07-05 23:33:18.000000000 +0200
@@ -138,9 +138,23 @@ static void ieee80211_setup_sdata(struct
ieee80211_debugfs_add_netdev(sdata);
}
-void ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_if_types type)
+int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_if_types type)
{
+ ASSERT_RTNL();
+
+ if (type == sdata->vif.type)
+ return 0;
+
+ /*
+ * We could, here, on changes between IBSS/STA/MESH modes,
+ * invoke an MLME function instead that disassociates etc.
+ * and goes into the requested mode.
+ */
+
+ if (netif_running(sdata->dev))
+ return -EBUSY;
+
/* Purge and reset type-dependent state. */
ieee80211_teardown_sdata(sdata->dev);
ieee80211_setup_sdata(sdata, type);
@@ -149,6 +163,8 @@ void ieee80211_if_change_type(struct iee
sdata->basic_rates = 0;
sdata->drop_unencrypted = 0;
sdata->sequence = 0;
+
+ return 0;
}
int ieee80211_if_add(struct ieee80211_local *local, const char *name,
--- everything.orig/net/mac80211/wext.c 2008-07-05 23:33:16.000000000 +0200
+++ everything/net/mac80211/wext.c 2008-07-05 23:33:18.000000000 +0200
@@ -296,14 +296,7 @@ static int ieee80211_ioctl_siwmode(struc
return -EINVAL;
}
- if (type == sdata->vif.type)
- return 0;
- if (netif_running(dev))
- return -EBUSY;
-
- ieee80211_if_change_type(sdata, type);
-
- return 0;
+ return ieee80211_if_change_type(sdata, type);
}
--
^ permalink raw reply [flat|nested] 10+ messages in thread* [RFT 4/4] mac80211: revamp beacon configuration
2008-07-05 23:47 [RFT 0/4] mac80211 improvements Johannes Berg
` (2 preceding siblings ...)
2008-07-05 23:47 ` [RFT 3/4] mac80211: push interface checks down Johannes Berg
@ 2008-07-05 23:47 ` Johannes Berg
2008-07-08 11:53 ` [RFT 0/4] mac80211 improvements Ivo van Doorn
4 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2008-07-05 23:47 UTC (permalink / raw)
To: linux-wireless
This patch changes mac80211's beacon configuration handling
to never pass skbs to the driver directly but rather always
require the driver to use ieee80211_beacon_get(). Additionally,
it introduces "change flags" on the config_interface() call
to enable drivers to figure out what is changing. Finally, it
removes the beacon_update() driver callback in favour of
having IBSS beacon delivered by ieee80211_beacon_get() as well.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/ath5k/base.c | 13 +++
drivers/net/wireless/b43/main.c | 48 +++++-------
drivers/net/wireless/b43legacy/main.c | 45 ++++-------
drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 ++++
drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 +++-
drivers/net/wireless/rt2x00/rt2400pci.c | 2
drivers/net/wireless/rt2x00/rt2500pci.c | 2
drivers/net/wireless/rt2x00/rt2500usb.c | 2
drivers/net/wireless/rt2x00/rt2x00.h | 2
drivers/net/wireless/rt2x00/rt2x00dev.c | 10 +-
drivers/net/wireless/rt2x00/rt2x00mac.c | 22 ++++-
drivers/net/wireless/rt2x00/rt61pci.c | 2
drivers/net/wireless/rt2x00/rt73usb.c | 2
drivers/net/wireless/zd1211rw/zd_mac.c | 21 +----
include/net/mac80211.h | 49 ++++--------
net/mac80211/cfg.c | 4 -
net/mac80211/ieee80211_i.h | 3
net/mac80211/main.c | 59 ++++++--------
net/mac80211/mlme.c | 112 +++++++++++-----------------
net/mac80211/tx.c | 36 +++++----
net/mac80211/wext.c | 2
21 files changed, 225 insertions(+), 248 deletions(-)
--- everything.orig/include/net/mac80211.h 2008-07-05 23:32:56.000000000 +0200
+++ everything/include/net/mac80211.h 2008-07-05 23:33:20.000000000 +0200
@@ -519,33 +519,38 @@ struct ieee80211_if_init_conf {
};
/**
+ * enum ieee80211_if_conf_change - interface config change flags
+ *
+ * @IEEE80211_IFCC_BSSID: The BSSID changed.
+ * @IEEE80211_IFCC_SSID: The SSID changed.
+ * @IEEE80211_IFCC_BEACON: The beacon for this interface changed
+ * (currently AP and MESH only), use ieee80211_beacon_get().
+ */
+enum ieee80211_if_conf_change {
+ IEEE80211_IFCC_BSSID = BIT(0),
+ IEEE80211_IFCC_SSID = BIT(1),
+ IEEE80211_IFCC_BEACON = BIT(2),
+};
+
+/**
* struct ieee80211_if_conf - configuration of an interface
*
- * @type: type of the interface. This is always the same as was specified in
- * &struct ieee80211_if_init_conf. The type of an interface never changes
- * during the life of the interface; this field is present only for
- * convenience.
+ * @changed: parameters that have changed, see &enum ieee80211_if_conf_change.
* @bssid: BSSID of the network we are associated to/creating.
* @ssid: used (together with @ssid_len) by drivers for hardware that
* generate beacons independently. The pointer is valid only during the
* config_interface() call, so copy the value somewhere if you need
* it.
* @ssid_len: length of the @ssid field.
- * @beacon: beacon template. Valid only if @host_gen_beacon_template in
- * &struct ieee80211_hw is set. The driver is responsible of freeing
- * the sk_buff.
- * @beacon_control: tx_control for the beacon template, this field is only
- * valid when the @beacon field was set.
*
* This structure is passed to the config_interface() callback of
* &struct ieee80211_hw.
*/
struct ieee80211_if_conf {
- int type;
+ u32 changed;
u8 *bssid;
u8 *ssid;
size_t ssid_len;
- struct sk_buff *beacon;
};
/**
@@ -673,15 +678,6 @@ enum ieee80211_tkip_key_type {
* any particular flags. There are some exceptions to this rule,
* however, so you are advised to review these flags carefully.
*
- * @IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE:
- * The device only needs to be supplied with a beacon template.
- * If you need the host to generate each beacon then don't use
- * this flag and call ieee80211_beacon_get() when you need the
- * next beacon frame. Note that if you set this flag, you must
- * implement the set_tim() callback for powersave mode to work
- * properly.
- * This flag is only relevant for access-point mode.
- *
* @IEEE80211_HW_RX_INCLUDES_FCS:
* Indicates that received frames passed to the stack include
* the FCS at the end.
@@ -1141,17 +1137,6 @@ enum ieee80211_ampdu_mlme_action {
* function is optional if the firmware/hardware takes full care of
* TSF synchronization.
*
- * @beacon_update: Setup beacon data for IBSS beacons. Unlike access point,
- * IBSS uses a fixed beacon frame which is configured using this
- * function.
- * If the driver returns success (0) from this callback, it owns
- * the skb. That means the driver is responsible to kfree_skb() it.
- * The control structure is not dynamically allocated. That means the
- * driver does not own the pointer and if it needs it somewhere
- * outside of the context of this function, it must copy it
- * somewhere else.
- * This handler is required only for IBSS mode.
- *
* @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
* This is needed only for IBSS mode and the result of this function is
* used to determine whether to reply to Probe Requests.
@@ -1209,8 +1194,6 @@ struct ieee80211_ops {
struct ieee80211_tx_queue_stats *stats);
u64 (*get_tsf)(struct ieee80211_hw *hw);
void (*reset_tsf)(struct ieee80211_hw *hw);
- int (*beacon_update)(struct ieee80211_hw *hw,
- struct sk_buff *skb);
int (*tx_last_beacon)(struct ieee80211_hw *hw);
int (*ampdu_action)(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
--- everything.orig/net/mac80211/cfg.c 2008-07-05 23:33:18.000000000 +0200
+++ everything/net/mac80211/cfg.c 2008-07-05 23:33:20.000000000 +0200
@@ -469,7 +469,7 @@ static int ieee80211_config_beacon(struc
kfree(old);
- return ieee80211_if_config_beacon(sdata->dev);
+ return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
}
static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
@@ -523,7 +523,7 @@ static int ieee80211_del_beacon(struct w
synchronize_rcu();
kfree(old);
- return ieee80211_if_config_beacon(dev);
+ return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
}
/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
--- everything.orig/net/mac80211/ieee80211_i.h 2008-07-05 23:33:18.000000000 +0200
+++ everything/net/mac80211/ieee80211_i.h 2008-07-05 23:33:20.000000000 +0200
@@ -854,8 +854,7 @@ static inline int ieee80211_bssid_match(
/* ieee80211.c */
int ieee80211_hw_config(struct ieee80211_local *local);
-int ieee80211_if_config(struct net_device *dev);
-int ieee80211_if_config_beacon(struct net_device *dev);
+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,
--- everything.orig/net/mac80211/main.c 2008-07-05 23:33:16.000000000 +0200
+++ everything/net/mac80211/main.c 2008-07-05 23:33:20.000000000 +0200
@@ -306,7 +306,8 @@ static int ieee80211_open(struct net_dev
if (res)
goto err_stop;
- ieee80211_if_config(dev);
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ ieee80211_start_mesh(sdata->dev);
ieee80211_reset_erp_info(dev);
ieee80211_enable_keys(sdata);
@@ -979,57 +980,47 @@ void ieee80211_if_setup(struct net_devic
/* everything else */
-static int __ieee80211_if_config(struct net_device *dev,
- struct sk_buff *beacon)
+int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
{
- 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 ieee80211_if_conf conf;
- if (!local->ops->config_interface || !netif_running(dev))
+ if (WARN_ON(!netif_running(sdata->dev)))
+ return 0;
+
+ if (!local->ops->config_interface)
return 0;
memset(&conf, 0, sizeof(conf));
- conf.type = sdata->vif.type;
+ conf.changed = changed;
+
if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
conf.bssid = sdata->u.sta.bssid;
conf.ssid = sdata->u.sta.ssid;
conf.ssid_len = sdata->u.sta.ssid_len;
- } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
- conf.beacon = beacon;
- ieee80211_start_mesh(dev);
} else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+ conf.bssid = sdata->dev->dev_addr;
conf.ssid = sdata->u.ap.ssid;
conf.ssid_len = sdata->u.ap.ssid_len;
- conf.beacon = beacon;
+ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
+ u8 zero[ETH_ALEN] = { 0 };
+ conf.bssid = zero;
+ conf.ssid = zero;
+ conf.ssid_len = 0;
+ } else {
+ WARN_ON(1);
+ return -EINVAL;
}
- return local->ops->config_interface(local_to_hw(local),
- &sdata->vif, &conf);
-}
-int ieee80211_if_config(struct net_device *dev)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT &&
- (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
- return ieee80211_if_config_beacon(dev);
- return __ieee80211_if_config(dev, NULL);
-}
+ if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
+ return -EINVAL;
-int ieee80211_if_config_beacon(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 sk_buff *skb;
+ if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID)))
+ return -EINVAL;
- if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
- return 0;
- skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif);
- if (!skb)
- return -ENOMEM;
- return __ieee80211_if_config(dev, skb);
+ return local->ops->config_interface(local_to_hw(local),
+ &sdata->vif, &conf);
}
int ieee80211_hw_config(struct ieee80211_local *local)
--- everything.orig/net/mac80211/mlme.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/mlme.c 2008-07-05 23:33:20.000000000 +0200
@@ -2403,8 +2403,6 @@ static int ieee80211_sta_join_ibss(struc
int res, rates, i, j;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
- struct ieee80211_tx_info *control;
- struct rate_selection ratesel;
u8 *pos;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_supported_band *sband;
@@ -2422,7 +2420,7 @@ static int ieee80211_sta_join_ibss(struc
local->ops->reset_tsf(local_to_hw(local));
}
memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
- res = ieee80211_if_config(dev);
+ res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
if (res)
return res;
@@ -2436,19 +2434,16 @@ static int ieee80211_sta_join_ibss(struc
if (res)
return res;
- /* Set beacon template */
+ /* Build IBSS probe response */
skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
- do {
- if (!skb)
- break;
-
+ if (skb) {
skb_reserve(skb, local->hw.extra_tx_headroom);
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_BEACON);
+ 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);
@@ -2492,61 +2487,22 @@ static int ieee80211_sta_join_ibss(struc
memcpy(pos, &bss->supp_rates[8], rates);
}
- control = IEEE80211_SKB_CB(skb);
-
- rate_control_get_rate(dev, sband, skb, &ratesel);
- if (ratesel.rate_idx < 0) {
- printk(KERN_DEBUG "%s: Failed to determine TX rate "
- "for IBSS beacon\n", dev->name);
- break;
- }
- control->control.vif = &sdata->vif;
- control->tx_rate_idx = ratesel.rate_idx;
- if (sdata->bss_conf.use_short_preamble &&
- sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
- control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
- control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
- control->flags |= IEEE80211_TX_CTL_NO_ACK;
- control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
- control->control.retry_limit = 1;
-
- ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
- if (ifsta->probe_resp) {
- mgmt = (struct ieee80211_mgmt *)
- ifsta->probe_resp->data;
- mgmt->frame_control =
- IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_PROBE_RESP);
- } else {
- printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
- "template for IBSS\n", dev->name);
- }
-
- if (local->ops->beacon_update &&
- local->ops->beacon_update(local_to_hw(local), skb) == 0) {
- printk(KERN_DEBUG "%s: Configured IBSS beacon "
- "template\n", dev->name);
- skb = NULL;
- }
+ ifsta->probe_resp = skb;
- rates = 0;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- for (i = 0; i < bss->supp_rates_len; i++) {
- int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
- for (j = 0; j < sband->n_bitrates; j++)
- if (sband->bitrates[j].bitrate == bitrate)
- rates |= BIT(j);
- }
- ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
-
- ieee80211_sta_def_wmm_params(dev, bss, 1);
- } while (0);
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+ }
- if (skb) {
- printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
- "template\n", dev->name);
- dev_kfree_skb(skb);
+ rates = 0;
+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ for (i = 0; i < bss->supp_rates_len; i++) {
+ int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+ for (j = 0; j < sband->n_bitrates; j++)
+ if (sband->bitrates[j].bitrate == bitrate)
+ rates |= BIT(j);
}
+ ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
+
+ ieee80211_sta_def_wmm_params(dev, bss, 1);
ifsta->state = IEEE80211_IBSS_JOINED;
mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
@@ -3330,7 +3286,7 @@ static void ieee80211_mesh_housekeeping(
free_plinks = mesh_plink_availables(sdata);
if (free_plinks != sdata->u.sta.accepting_plinks)
- ieee80211_if_config_beacon(dev);
+ ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
mod_timer(&ifsta->timer, jiffies +
IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
@@ -3752,28 +3708,45 @@ int ieee80211_sta_set_ssid(struct net_de
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_if_sta *ifsta;
+ int res;
if (len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
ifsta = &sdata->u.sta;
- if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
+ 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;
- memcpy(ifsta->ssid, ssid, len);
- memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
- ifsta->ssid_len = len;
+
+ 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", dev->name);
+ return res;
+ }
+ }
if (len)
ifsta->flags |= IEEE80211_STA_SSID_SET;
else
ifsta->flags &= ~IEEE80211_STA_SSID_SET;
+
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
!(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
ifsta->ibss_join_req = jiffies;
ifsta->state = IEEE80211_IBSS_SEARCH;
return ieee80211_sta_find_ibss(dev, ifsta);
}
+
return 0;
}
@@ -3799,7 +3772,12 @@ int ieee80211_sta_set_bssid(struct net_d
if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
memcpy(ifsta->bssid, bssid, ETH_ALEN);
- res = ieee80211_if_config(dev);
+ 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", dev->name);
--- everything.orig/net/mac80211/wext.c 2008-07-05 23:33:18.000000000 +0200
+++ everything/net/mac80211/wext.c 2008-07-05 23:33:20.000000000 +0200
@@ -444,7 +444,7 @@ static int ieee80211_ioctl_siwessid(stru
memset(sdata->u.ap.ssid + len, 0,
IEEE80211_MAX_SSID_LEN - len);
sdata->u.ap.ssid_len = len;
- return ieee80211_if_config(dev);
+ return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
}
return -EOPNOTSUPP;
}
--- everything.orig/drivers/net/wireless/b43/main.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/b43/main.c 2008-07-05 23:33:20.000000000 +0200
@@ -1675,14 +1675,24 @@ static void b43_beacon_update_trigger_wo
/* Asynchronously update the packet templates in template RAM.
* Locking: Requires wl->irq_lock to be locked. */
-static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
+static void b43_update_templates(struct b43_wl *wl)
{
+ struct sk_buff *beacon;
+
/* This is the top half of the ansynchronous beacon update.
* The bottom half is the beacon IRQ.
* Beacon update must be asynchronous to avoid sending an
* invalid beacon. This can happen for example, if the firmware
* transmits a beacon while we are updating it. */
+ /* We could modify the existing beacon and set the aid bit in
+ * the TIM field, but that would probably require resizing and
+ * moving of data within the beacon template.
+ * Simply request a new beacon and let mac80211 do the hard work. */
+ beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+ if (unlikely(!beacon))
+ return;
+
if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
@@ -3645,10 +3655,14 @@ static int b43_op_config_interface(struc
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)) {
- B43_WARN_ON(conf->type != wl->if_type);
- b43_set_ssid(dev, conf->ssid, conf->ssid_len);
- if (conf->beacon)
- b43_update_templates(wl, conf->beacon);
+ 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)) {
+ if (conf->changed & IEEE80211_IFCC_BEACON)
+ b43_update_templates(wl);
}
b43_write_mac_bssid_templates(dev);
}
@@ -4336,31 +4350,10 @@ out_unlock:
static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- struct sk_buff *beacon;
- unsigned long flags;
-
- /* We could modify the existing beacon and set the aid bit in
- * the TIM field, but that would probably require resizing and
- * moving of data within the beacon template.
- * Simply request a new beacon and let mac80211 do the hard work. */
- beacon = ieee80211_beacon_get(hw, wl->vif);
- if (unlikely(!beacon))
- return -ENOMEM;
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43_update_templates(wl, beacon);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
- return 0;
-}
-
-static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
- struct sk_buff *beacon)
-{
- struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;
spin_lock_irqsave(&wl->irq_lock, flags);
- b43_update_templates(wl, beacon);
+ b43_update_templates(wl);
spin_unlock_irqrestore(&wl->irq_lock, flags);
return 0;
@@ -4391,7 +4384,6 @@ static const struct ieee80211_ops b43_hw
.stop = b43_op_stop,
.set_retry_limit = b43_op_set_retry_limit,
.set_tim = b43_op_beacon_set_tim,
- .beacon_update = b43_op_ibss_beacon_update,
.sta_notify = b43_op_sta_notify,
};
--- everything.orig/drivers/net/wireless/ath5k/base.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/ath5k/base.c 2008-07-05 23:33:20.000000000 +0200
@@ -207,7 +207,6 @@ static struct ieee80211_ops ath5k_hw_ops
.get_tx_stats = ath5k_get_tx_stats,
.get_tsf = ath5k_get_tsf,
.reset_tsf = ath5k_reset_tsf,
- .beacon_update = ath5k_beacon_update,
};
/*
@@ -2785,6 +2784,18 @@ ath5k_config_interface(struct ieee80211_
* a clean way of letting us retrieve this yet. */
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
}
+
+ if (conf->changed & IEEE80211_IFCC_BEACON &&
+ vif->type == IEEE80211_IF_TYPE_IBSS) {
+ struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+ if (!beacon) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+ /* call old handler for now */
+ ath5k_beacon_update(hw, beacon);
+ }
+
mutex_unlock(&sc->lock);
return ath5k_reset(hw);
--- everything.orig/drivers/net/wireless/b43legacy/main.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/b43legacy/main.c 2008-07-05 23:33:20.000000000 +0200
@@ -1138,14 +1138,22 @@ static void b43legacy_write_probe_resp_t
/* Asynchronously update the packet templates in template RAM.
* Locking: Requires wl->irq_lock to be locked. */
-static void b43legacy_update_templates(struct b43legacy_wl *wl,
- struct sk_buff *beacon)
+static void b43legacy_update_templates(struct b43legacy_wl *wl)
{
+ struct sk_buff *beacon;
/* This is the top half of the ansynchronous beacon update. The bottom
* half is the beacon IRQ. Beacon update must be asynchronous to avoid
* sending an invalid beacon. This can happen for example, if the
* firmware transmits a beacon while we are updating it. */
+ /* We could modify the existing beacon and set the aid bit in the TIM
+ * field, but that would probably require resizing and moving of data
+ * within the beacon template. Simply request a new beacon and let
+ * mac80211 do the hard work. */
+ beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+ if (unlikely(!beacon))
+ return;
+
if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
@@ -2727,10 +2735,13 @@ static int b43legacy_op_config_interface
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(conf->type != IEEE80211_IF_TYPE_AP);
+ B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP);
b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
- if (conf->beacon)
- b43legacy_update_templates(wl, conf->beacon);
+ if (conf->changed & IEEE80211_IFCC_BEACON)
+ b43legacy_update_templates(wl);
+ } else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
+ if (conf->changed & IEEE80211_IFCC_BEACON)
+ b43legacy_update_templates(wl);
}
b43legacy_write_mac_bssid_templates(dev);
}
@@ -3396,31 +3407,10 @@ static int b43legacy_op_beacon_set_tim(s
int aid, int set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct sk_buff *beacon;
- unsigned long flags;
-
- /* We could modify the existing beacon and set the aid bit in the TIM
- * field, but that would probably require resizing and moving of data
- * within the beacon template. Simply request a new beacon and let
- * mac80211 do the hard work. */
- beacon = ieee80211_beacon_get(hw, wl->vif);
- if (unlikely(!beacon))
- return -ENOMEM;
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43legacy_update_templates(wl, beacon);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
- return 0;
-}
-
-static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
- struct sk_buff *beacon)
-{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
spin_lock_irqsave(&wl->irq_lock, flags);
- b43legacy_update_templates(wl, beacon);
+ b43legacy_update_templates(wl);
spin_unlock_irqrestore(&wl->irq_lock, flags);
return 0;
@@ -3440,7 +3430,6 @@ static const struct ieee80211_ops b43leg
.stop = b43legacy_op_stop,
.set_retry_limit = b43legacy_op_set_retry_limit,
.set_tim = b43legacy_op_beacon_set_tim,
- .beacon_update = b43legacy_op_ibss_beacon_update,
};
/* Hard-reset the chip. Do not call this directly.
--- everything.orig/drivers/net/wireless/iwlwifi/iwl3945-base.c 2008-07-05 23:32:56.000000000 +0200
+++ everything/drivers/net/wireless/iwlwifi/iwl3945-base.c 2008-07-05 23:33:20.000000000 +0200
@@ -6889,6 +6889,9 @@ static void iwl3945_config_ap(struct iwl
* clear sta table, add BCAST sta... */
}
+/* temporary */
+static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+
static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
@@ -6906,10 +6909,21 @@ static int iwl3945_mac_config_interface(
return 0;
}
+ /* handle this temporarily here */
+ if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+ conf->changed & IEEE80211_IFCC_BEACON) {
+ struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+ if (!beacon)
+ return -ENOMEM;
+ rc = iwl3945_mac_beacon_update(hw, beacon);
+ if (rc)
+ return rc;
+ }
+
/* XXX: this MUST use conf->mac_addr */
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
- (!conf->beacon || !conf->ssid_len)) {
+ (!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
return 0;
@@ -6941,7 +6955,7 @@ static int iwl3945_mac_config_interface(
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = conf->beacon;
+ priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
}
if (iwl3945_is_rfkill(priv))
@@ -7922,7 +7936,6 @@ static struct ieee80211_ops iwl3945_hw_o
.conf_tx = iwl3945_mac_conf_tx,
.get_tsf = iwl3945_mac_get_tsf,
.reset_tsf = iwl3945_mac_reset_tsf,
- .beacon_update = iwl3945_mac_beacon_update,
.hw_scan = iwl3945_mac_hw_scan
};
--- everything.orig/drivers/net/wireless/iwlwifi/iwl4965-base.c 2008-07-05 23:32:56.000000000 +0200
+++ everything/drivers/net/wireless/iwlwifi/iwl4965-base.c 2008-07-05 23:33:20.000000000 +0200
@@ -2912,6 +2912,9 @@ static void iwl4965_config_ap(struct iwl
* clear sta table, add BCAST sta... */
}
+/* temporary */
+static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+
static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
@@ -2929,8 +2932,18 @@ static int iwl4965_mac_config_interface(
return 0;
}
+ if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+ conf->changed & IEEE80211_IFCC_BEACON) {
+ struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+ if (!beacon)
+ return -ENOMEM;
+ rc = iwl4965_mac_beacon_update(hw, beacon);
+ if (rc)
+ return rc;
+ }
+
if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
- (!conf->beacon || !conf->ssid_len)) {
+ (!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
return 0;
@@ -2962,7 +2975,7 @@ static int iwl4965_mac_config_interface(
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
- priv->ibss_beacon = conf->beacon;
+ priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
}
if (iwl_is_rfkill(priv))
@@ -4090,7 +4103,6 @@ static struct ieee80211_ops iwl4965_hw_o
.get_tx_stats = iwl4965_mac_get_tx_stats,
.conf_tx = iwl4965_mac_conf_tx,
.reset_tsf = iwl4965_mac_reset_tsf,
- .beacon_update = iwl4965_mac_beacon_update,
.bss_info_changed = iwl4965_bss_info_changed,
.ampdu_action = iwl4965_mac_ampdu_action,
.hw_scan = iwl4965_mac_hw_scan
--- everything.orig/drivers/net/wireless/rt2x00/rt2400pci.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt2400pci.c 2008-07-05 23:33:20.000000000 +0200
@@ -1558,7 +1558,6 @@ static const struct ieee80211_ops rt2400
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
- .beacon_update = rt2400pci_beacon_update,
.tx_last_beacon = rt2400pci_tx_last_beacon,
};
@@ -1578,6 +1577,7 @@ static const struct rt2x00lib_ops rt2400
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt2400pci_kick_tx_queue,
.fill_rxdone = rt2400pci_fill_rxdone,
+ .beacon_update = rt2400pci_beacon_update,
.config_filter = rt2400pci_config_filter,
.config_intf = rt2400pci_config_intf,
.config_erp = rt2400pci_config_erp,
--- everything.orig/drivers/net/wireless/rt2x00/rt2500pci.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt2500pci.c 2008-07-05 23:33:20.000000000 +0200
@@ -1875,7 +1875,6 @@ static const struct ieee80211_ops rt2500
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
- .beacon_update = rt2500pci_beacon_update,
.tx_last_beacon = rt2500pci_tx_last_beacon,
};
@@ -1895,6 +1894,7 @@ static const struct rt2x00lib_ops rt2500
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt2500pci_kick_tx_queue,
.fill_rxdone = rt2500pci_fill_rxdone,
+ .beacon_update = rt2500pci_beacon_update,
.config_filter = rt2500pci_config_filter,
.config_intf = rt2500pci_config_intf,
.config_erp = rt2500pci_config_erp,
--- everything.orig/drivers/net/wireless/rt2x00/rt2500usb.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt2500usb.c 2008-07-05 23:33:20.000000000 +0200
@@ -1775,7 +1775,6 @@ static const struct ieee80211_ops rt2500
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
- .beacon_update = rt2500usb_beacon_update,
};
static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1793,6 +1792,7 @@ static const struct rt2x00lib_ops rt2500
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2500usb_kick_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
+ .beacon_update = rt2500usb_beacon_update,
.config_filter = rt2500usb_config_filter,
.config_intf = rt2500usb_config_intf,
.config_erp = rt2500usb_config_erp,
--- everything.orig/drivers/net/wireless/rt2x00/rt2x00.h 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt2x00.h 2008-07-05 23:33:20.000000000 +0200
@@ -534,6 +534,8 @@ struct rt2x00lib_ops {
/*
* Configuration handlers.
*/
+ int (*beacon_update) (struct ieee80211_hw *hw, struct sk_buff *bcn);
+
void (*config_filter) (struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void (*config_intf) (struct rt2x00_dev *rt2x00dev,
--- everything.orig/drivers/net/wireless/rt2x00/rt2x00dev.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt2x00dev.c 2008-07-05 23:33:20.000000000 +0200
@@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_ite
{
struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif);
- struct sk_buff *skb;
struct ieee80211_bss_conf conf;
int delayed_flags;
@@ -436,10 +435,11 @@ static void rt2x00lib_intf_scheduled_ite
return;
if (delayed_flags & DELAYED_UPDATE_BEACON) {
- skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
- if (skb &&
- rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb))
- dev_kfree_skb(skb);
+ struct ieee80211_if_conf conf;
+ conf.bssid = conf.ssid = NULL;
+ conf.ssid_len = 0;
+ conf.changed = IEEE80211_IFCC_BEACON;
+ rt2x00dev->ops->hw->config_interface(rt2x00dev->hw, vif, &conf);
}
if (delayed_flags & DELAYED_CONFIG_ERP)
--- everything.orig/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-07-05 23:33:20.000000000 +0200
@@ -348,6 +348,7 @@ int rt2x00mac_config_interface(struct ie
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_intf *intf = vif_to_intf(vif);
+ struct sk_buff *beacon;
int status;
/*
@@ -363,8 +364,11 @@ int rt2x00mac_config_interface(struct ie
* If the interface does not work in master mode,
* then the bssid value in the interface structure
* should now be set.
+ *
+ * conf->bssid can be NULL if coming from the internal
+ * beacon update routine.
*/
- if (conf->type != IEEE80211_IF_TYPE_AP)
+ if (conf->bssid && vif->type != IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
spin_unlock(&intf->lock);
@@ -375,17 +379,23 @@ int rt2x00mac_config_interface(struct ie
* values as arguments we make keep access to rt2x00_intf thread safe
* even without the lock.
*/
- rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid);
+ rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, conf->bssid);
/*
- * We only need to initialize the beacon when master mode is enabled.
+ * We only need to initialize the beacon when in master/ibss mode.
*/
- if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon)
+ if ((vif->type != IEEE80211_IF_TYPE_AP &&
+ vif->type != IEEE80211_IF_TYPE_IBSS) ||
+ !(conf->changed & IEEE80211_IFCC_BEACON))
return 0;
- status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon);
+ beacon = ieee80211_beacon_get(rt2x00dev->hw, vif);
+ if (!beacon)
+ return -ENOMEM;
+
+ status = rt2x00dev->ops->lib->beacon_update(rt2x00dev->hw, beacon);
if (status)
- dev_kfree_skb(conf->beacon);
+ dev_kfree_skb(beacon);
return status;
}
--- everything.orig/drivers/net/wireless/rt2x00/rt61pci.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt61pci.c 2008-07-05 23:33:20.000000000 +0200
@@ -2427,7 +2427,6 @@ static const struct ieee80211_ops rt61pc
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
- .beacon_update = rt61pci_beacon_update,
};
static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -2449,6 +2448,7 @@ static const struct rt2x00lib_ops rt61pc
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt61pci_kick_tx_queue,
.fill_rxdone = rt61pci_fill_rxdone,
+ .beacon_update = rt61pci_beacon_update,
.config_filter = rt61pci_config_filter,
.config_intf = rt61pci_config_intf,
.config_erp = rt61pci_config_erp,
--- everything.orig/drivers/net/wireless/rt2x00/rt73usb.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/rt2x00/rt73usb.c 2008-07-05 23:33:20.000000000 +0200
@@ -2031,7 +2031,6 @@ static const struct ieee80211_ops rt73us
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
- .beacon_update = rt73usb_beacon_update,
};
static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2052,6 +2051,7 @@ static const struct rt2x00lib_ops rt73us
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt73usb_kick_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
+ .beacon_update = rt73usb_beacon_update,
.config_filter = rt73usb_config_filter,
.config_intf = rt73usb_config_intf,
.config_erp = rt73usb_config_erp,
--- everything.orig/drivers/net/wireless/zd1211rw/zd_mac.c 2008-07-05 23:32:57.000000000 +0200
+++ everything/drivers/net/wireless/zd1211rw/zd_mac.c 2008-07-05 23:33:20.000000000 +0200
@@ -703,9 +703,12 @@ static int zd_op_config_interface(struct
if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
mac->type == IEEE80211_IF_TYPE_IBSS) {
associated = true;
- if (conf->beacon) {
- zd_mac_config_beacon(hw, conf->beacon);
- kfree_skb(conf->beacon);
+ if (conf->changed & IEEE80211_IFCC_BEACON) {
+ struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+ if (!beacon)
+ return -ENOMEM;
+ zd_mac_config_beacon(hw, beacon);
+ kfree_skb(beacon);
zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
hw->conf.beacon_int);
}
@@ -861,17 +864,6 @@ static void zd_op_bss_info_changed(struc
}
}
-static int zd_op_beacon_update(struct ieee80211_hw *hw,
- struct sk_buff *skb)
-{
- struct zd_mac *mac = zd_hw_mac(hw);
- zd_mac_config_beacon(hw, skb);
- kfree_skb(skb);
- zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
- hw->conf.beacon_int);
- return 0;
-}
-
static const struct ieee80211_ops zd_ops = {
.tx = zd_op_tx,
.start = zd_op_start,
@@ -882,7 +874,6 @@ static const struct ieee80211_ops zd_ops
.config_interface = zd_op_config_interface,
.configure_filter = zd_op_configure_filter,
.bss_info_changed = zd_op_bss_info_changed,
- .beacon_update = zd_op_beacon_update,
};
struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
--- everything.orig/net/mac80211/tx.c 2008-07-05 23:33:10.000000000 +0200
+++ everything/net/mac80211/tx.c 2008-07-05 23:33:20.000000000 +0200
@@ -1795,17 +1795,17 @@ struct sk_buff *ieee80211_beacon_get(str
struct ieee80211_vif *vif)
{
struct ieee80211_local *local = hw_to_local(hw);
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
struct ieee80211_tx_info *info;
struct net_device *bdev;
struct ieee80211_sub_if_data *sdata = NULL;
struct ieee80211_if_ap *ap = NULL;
+ struct ieee80211_if_sta *ifsta = NULL;
struct rate_selection rsel;
struct beacon_data *beacon;
struct ieee80211_supported_band *sband;
struct ieee80211_mgmt *mgmt;
int *num_beacons;
- bool err = true;
enum ieee80211_band band = local->hw.conf.channel->band;
u8 *pos;
@@ -1859,9 +1859,24 @@ struct sk_buff *ieee80211_beacon_get(str
beacon->tail, beacon->tail_len);
num_beacons = &ap->num_beacons;
+ } else
+ goto out;
+ } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+ struct ieee80211_hdr *hdr;
+ ifsta = &sdata->u.sta;
- err = false;
- }
+ if (!ifsta->probe_resp)
+ goto out;
+
+ skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC);
+ if (!skb)
+ goto out;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+ IEEE80211_STYPE_BEACON);
+
+ num_beacons = &ifsta->num_beacons;
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
/* headroom, head length, tail length and maximum TIM length */
skb = dev_alloc_skb(local->tx_headroom + 400);
@@ -1888,17 +1903,8 @@ struct sk_buff *ieee80211_beacon_get(str
mesh_mgmt_ies_add(skb, sdata->dev);
num_beacons = &sdata->u.sta.num_beacons;
-
- err = false;
- }
-
- if (err) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "no beacon data avail for %s\n",
- bdev->name);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
- skb = NULL;
+ } else {
+ WARN_ON(1);
goto out;
}
--
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFT 0/4] mac80211 improvements
2008-07-05 23:47 [RFT 0/4] mac80211 improvements Johannes Berg
` (3 preceding siblings ...)
2008-07-05 23:47 ` [RFT 4/4] mac80211: revamp beacon configuration Johannes Berg
@ 2008-07-08 11:53 ` Ivo van Doorn
2008-07-08 11:51 ` Johannes Berg
4 siblings, 1 reply; 10+ messages in thread
From: Ivo van Doorn @ 2008-07-08 11:53 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On Sunday 06 July 2008, Johannes Berg wrote:
> Here are a number of improvements for mac80211's virtual interface
> handling (master netdev, cleanups) and driver API (beaconing).
>
> I have tested these patches on b43 in AP, STA and IBSS modes
> (communicating with my N810 or an AP) and have not seen any issues.
>
> I would appreciate testing on other hardware (I can probably cover
> iwl4965, rt61pci and zd1211 next week), but I don't expect much
> trouble.
I have added these patches to rt2x00.git for testing purposes.
And to be more precise, the following patches have been added:
004-mac80211-master-not-ap.patch
005-mac80211-iface-cleanups.patch
006-mac80211-push-alive-check-down.patch
007-mac80211-beacon-revamp.patch
008-deprecate-sys-wireless.patch
009-local-bh-enable-consolidate.patch
010-linux-radiotap-rxflags.patch
011-allow-ap-vlan-modes.patch
Ivo
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFT 0/4] mac80211 improvements
2008-07-08 11:53 ` [RFT 0/4] mac80211 improvements Ivo van Doorn
@ 2008-07-08 11:51 ` Johannes Berg
0 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2008-07-08 11:51 UTC (permalink / raw)
To: Ivo van Doorn; +Cc: linux-wireless
[-- Attachment #1: Type: text/plain, Size: 1386 bytes --]
On Tue, 2008-07-08 at 13:53 +0200, Ivo van Doorn wrote:
> On Sunday 06 July 2008, Johannes Berg wrote:
> > Here are a number of improvements for mac80211's virtual interface
> > handling (master netdev, cleanups) and driver API (beaconing).
> >
> > I have tested these patches on b43 in AP, STA and IBSS modes
> > (communicating with my N810 or an AP) and have not seen any issues.
> >
> > I would appreciate testing on other hardware (I can probably cover
> > iwl4965, rt61pci and zd1211 next week), but I don't expect much
> > trouble.
>
> I have added these patches to rt2x00.git for testing purposes.
Cool, thanks, let me know of any problems.
> And to be more precise, the following patches have been added:
>
> 004-mac80211-master-not-ap.patch
> 005-mac80211-iface-cleanups.patch
> 006-mac80211-push-alive-check-down.patch
> 007-mac80211-beacon-revamp.patch
Those I intend to push soonish.
> 008-deprecate-sys-wireless.patch
That one too, but hal (depends on it, patch is in git) needs a new
release first I guess.
> 009-local-bh-enable-consolidate.patch
Ingo Molnar is handling that one.
> 010-linux-radiotap-rxflags.patch
Pending radiotap list discussion about those new things, but I'm fairly
confident I'll post this one too this or next week.
> 011-allow-ap-vlan-modes.patch
Well that we all know about :)
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread