Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 90085
b: refs/heads/master
c: 44213b5
h: refs/heads/master
i:
  90083: 640a42f
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Mar 6, 2008
1 parent b078da5 commit e2d3ce5
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 84 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 693b1bbcc47b3fd436068f294147357f90cd1296
refs/heads/master: 44213b5e13c907bf4aa2e73941944f90184c8772
99 changes: 42 additions & 57 deletions trunk/net/mac80211/ieee80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ static int ieee80211_open(struct net_device *dev)
struct ieee80211_if_init_conf conf;
int res;
bool need_hw_reconfig = 0;
struct sta_info *sta;

sdata = IEEE80211_DEV_TO_SUB_IF(dev);

Expand Down Expand Up @@ -256,6 +257,20 @@ static int ieee80211_open(struct net_device *dev)
case IEEE80211_IF_TYPE_WDS:
if (is_zero_ether_addr(sdata->u.wds.remote_addr))
return -ENOLINK;

/* Create STA entry for the WDS peer */
sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
GFP_KERNEL);
if (!sta)
return -ENOMEM;

sta->flags |= WLAN_STA_AUTHORIZED;

res = sta_info_insert(sta);
if (res) {
sta_info_destroy(sta);
return res;
}
break;
case IEEE80211_IF_TYPE_VLAN:
if (!sdata->u.vlan.ap)
Expand Down Expand Up @@ -367,14 +382,20 @@ static int ieee80211_open(struct net_device *dev)

static int ieee80211_stop(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_init_conf conf;
struct sta_info *sta;
int i;

sdata = IEEE80211_DEV_TO_SUB_IF(dev);
/*
* Stop TX on this interface first.
*/
netif_stop_queue(dev);

/*
* Now delete all active aggregation sessions.
*/
rcu_read_lock();

list_for_each_entry_rcu(sta, &local->sta_list, list) {
Expand All @@ -388,7 +409,24 @@ static int ieee80211_stop(struct net_device *dev)

rcu_read_unlock();

netif_stop_queue(dev);
/*
* Remove all stations associated with this interface.
*
* This must be done before calling ops->remove_interface()
* because otherwise we can later invoke ops->sta_notify()
* whenever the STAs are removed, and that invalidates driver
* assumptions about always getting a vif pointer that is valid
* (because if we remove a STA after ops->remove_interface()
* the driver will have removed the vif info already!)
*
* We could relax this and only unlink the stations from the
* hash table and list but keep them on a per-sdata list that
* will be inserted back again when the interface is brought
* up again, but I don't currently see a use case for that,
* except with WDS which gets a STA entry created when it is
* brought up.
*/
sta_info_flush(local, sdata);

/*
* Don't count this interface for promisc/allmulti while it
Expand Down Expand Up @@ -453,8 +491,6 @@ static int ieee80211_stop(struct net_device *dev)
netif_tx_unlock_bh(local->mdev);
break;
case IEEE80211_IF_TYPE_MESH_POINT:
sta_info_flush(local, sdata);
/* fall through */
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_IBSS:
sdata->u.sta.state = IEEE80211_DISABLED;
Expand Down Expand Up @@ -892,57 +928,6 @@ void ieee80211_if_setup(struct net_device *dev)
dev->destructor = ieee80211_if_free;
}

/* WDS specialties */

int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct sta_info *sta;
int err;
DECLARE_MAC_BUF(mac);

might_sleep();

if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
return 0;

/* Create STA entry for the new peer */
sta = sta_info_alloc(sdata, remote_addr, GFP_KERNEL);
if (!sta)
return -ENOMEM;

sta->flags |= WLAN_STA_AUTHORIZED;
err = sta_info_insert(sta);
if (err) {
sta_info_destroy(sta);
return err;
}

rcu_read_lock();

/* Remove STA entry for the old peer */
sta = sta_info_get(local, sdata->u.wds.remote_addr);
if (sta)
sta_info_unlink(&sta);
else
printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
"peer %s\n",
dev->name, print_mac(mac, sdata->u.wds.remote_addr));

/* Update WDS link data */
memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);

rcu_read_unlock();

if (sta) {
synchronize_rcu();
sta_info_destroy(sta);
}

return 0;
}

/* everything else */

static int __ieee80211_if_config(struct net_device *dev,
Expand Down
1 change: 0 additions & 1 deletion trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,6 @@ 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);
void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
void ieee80211_if_setup(struct net_device *dev);
int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
struct ieee80211_ht_info *req_ht_cap,
Expand Down
22 changes: 4 additions & 18 deletions trunk/net/mac80211/ieee80211_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ void ieee80211_if_reinit(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 sta_info *sta;
struct sk_buff *skb;
int flushed;

ASSERT_RTNL();

Expand Down Expand Up @@ -240,21 +240,7 @@ void ieee80211_if_reinit(struct net_device *dev)
break;
}
case IEEE80211_IF_TYPE_WDS:
rcu_read_lock();
sta = sta_info_get(local, sdata->u.wds.remote_addr);
if (sta) {
sta_info_unlink(&sta);
} else {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "%s: Someone had deleted my STA "
"entry for the WDS link\n", dev->name);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
}
rcu_read_unlock();
if (sta) {
synchronize_rcu();
sta_info_destroy(sta);
}
/* nothing to do */
break;
case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
Expand All @@ -279,8 +265,8 @@ void ieee80211_if_reinit(struct net_device *dev)
break;
}

/* remove all STAs that are bound to this virtual interface */
sta_info_flush(local, sdata);
flushed = sta_info_flush(local, sdata);
WARN_ON(flushed);

memset(&sdata->u, 0, sizeof(sdata->u));
ieee80211_if_sdata_init(sdata);
Expand Down
18 changes: 14 additions & 4 deletions trunk/net/mac80211/ieee80211_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,10 +468,20 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
ieee80211_sta_req_auth(dev, &sdata->u.sta);
return 0;
} else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
ETH_ALEN) == 0)
return 0;
return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
/*
* If it is necessary to update the WDS peer address
* while the interface is running, then we need to do
* more work here, namely if it is running we need to
* add a new and remove the old STA entry, this is
* normally handled by _open() and _stop().
*/
if (netif_running(dev))
return -EBUSY;

memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
ETH_ALEN);

return 0;
}

return -EOPNOTSUPP;
Expand Down
14 changes: 12 additions & 2 deletions trunk/net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@ int sta_info_insert(struct sta_info *sta)
unsigned long flags;
DECLARE_MAC_BUF(mac);

WARN_ON(!netif_running(sdata->dev));

spin_lock_irqsave(&local->sta_lock, flags);
/* check if STA exists already */
if (__sta_info_find(local, sta->addr)) {
Expand Down Expand Up @@ -608,14 +610,18 @@ void sta_info_stop(struct ieee80211_local *local)

/**
* sta_info_flush - flush matching STA entries from the STA table
*
* Returns the number of removed STA entries.
*
* @local: local interface data
* @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
*/
void sta_info_flush(struct ieee80211_local *local,
int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
struct sta_info *sta, *tmp;
LIST_HEAD(tmp_list);
int ret = 0;
unsigned long flags;

might_sleep();
Expand All @@ -624,8 +630,10 @@ void sta_info_flush(struct ieee80211_local *local,
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
if (!sdata || sdata == sta->sdata) {
__sta_info_unlink(&sta);
if (sta)
if (sta) {
list_add_tail(&sta->list, &tmp_list);
ret++;
}
}
}
spin_unlock_irqrestore(&local->sta_lock, flags);
Expand All @@ -634,4 +642,6 @@ void sta_info_flush(struct ieee80211_local *local,

list_for_each_entry_safe(sta, tmp, &tmp_list, list)
sta_info_destroy(sta);

return ret;
}
2 changes: 1 addition & 1 deletion trunk/net/mac80211/sta_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta);
void sta_info_init(struct ieee80211_local *local);
int sta_info_start(struct ieee80211_local *local);
void sta_info_stop(struct ieee80211_local *local);
void sta_info_flush(struct ieee80211_local *local,
int sta_info_flush(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);

#endif /* STA_INFO_H */

0 comments on commit e2d3ce5

Please sign in to comment.