From f698d856f65c3fea091cc303a135967965c5b880 Mon Sep 17 00:00:00 2001 From: Jasper Bryant-Greene Date: Sun, 3 Aug 2008 12:04:37 +1200 Subject: replace net_device arguments with ieee80211_{local,sub_if_data} as appropriate This patch replaces net_device arguments to mac80211 internal functions with ieee80211_{local,sub_if_data} as appropriate. It also does the same for many 802.11s mesh functions, and changes the mesh path table to be indexed on sub_if_data rather than net_device. If the mesh part needs to be a separate patch let me know, but since mesh uses a lot of mac80211 functions which were being converted anyway, the changes go hand-in-hand somewhat. This patch probably does not convert all the functions which could be converted, but it is a large chunk and followup patches will be provided. Signed-off-by: Jasper Bryant-Greene Signed-off-by: John W. Linville --- net/mac80211/mesh.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b5933b27149..b631703bcc8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -39,14 +39,13 @@ void ieee80211s_stop(void) * mesh_matches_local - check if the config of a mesh point matches ours * * @ie: information elements of a management frame from the mesh peer - * @dev: local mesh interface + * @sdata: local mesh subif * * This function checks if the mesh configuration of a mesh point matches the * local mesh configuration, i.e. if both nodes belong to the same mesh network. */ -bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) +bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *sta = &sdata->u.sta; /* @@ -73,10 +72,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links * * @ie: information elements of a management frame from the mesh peer - * @dev: local mesh interface */ -bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, - struct net_device *dev) +bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) { return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; } @@ -111,9 +108,8 @@ void mesh_ids_set_default(struct ieee80211_if_sta *sta) memcpy(sta->mesh_cc_id, def_id, 4); } -int mesh_rmc_init(struct net_device *dev) +int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int i; sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); @@ -125,9 +121,8 @@ int mesh_rmc_init(struct net_device *dev) return 0; } -void mesh_rmc_free(struct net_device *dev) +void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_rmc *rmc = sdata->u.sta.rmc; struct rmc_entry *p, *n; int i; @@ -158,9 +153,8 @@ void mesh_rmc_free(struct net_device *dev) * it. */ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, - struct net_device *dev) + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_rmc *rmc = sdata->u.sta.rmc; u32 seqnum = 0; int entries = 0; @@ -194,10 +188,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, return 0; } -void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) +void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; u8 *pos; int len, i, rate; @@ -262,10 +255,10 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) return; } -u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl) +u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) { /* Use last four bytes of hw addr and interface index as hash index */ - return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd) + return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) & tbl->hash_mask; } @@ -434,7 +427,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ifsta->preq_id = 0; ifsta->dsn = 0; atomic_set(&ifsta->mpaths, 0); - mesh_rmc_init(sdata->dev); + mesh_rmc_init(sdata); ifsta->last_preq = jiffies; /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) -- cgit v1.2.3-70-g09d2 From 472dbc45dc1966284de72d7de15690c17ed2cf33 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:49 +0200 Subject: mac80211: split off mesh handling entirely This patch splits off mesh handling from the STA/IBSS. Unfortunately it increases mesh code size a bit, but I think it makes things clearer. The patch also reduces per-interface run-time memory usage. Also clean up a few places where ifdef is not required. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 6 +- net/mac80211/debugfs_netdev.c | 38 ++--- net/mac80211/ieee80211_i.h | 101 +++++++------ net/mac80211/iface.c | 13 +- net/mac80211/main.c | 13 +- net/mac80211/mesh.c | 328 +++++++++++++++++++++++++++++++++------- net/mac80211/mesh.h | 15 +- net/mac80211/mesh_hwmp.c | 98 ++++++------ net/mac80211/mesh_pathtbl.c | 8 +- net/mac80211/mesh_plink.c | 18 +-- net/mac80211/mlme.c | 83 +--------- net/mac80211/rc80211_pid_algo.c | 7 +- net/mac80211/rx.c | 8 +- net/mac80211/scan.c | 1 + net/mac80211/tx.c | 15 +- 15 files changed, 457 insertions(+), 295 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5a3bdaad6c1..6ec2127f9a6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -116,9 +116,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, return ret; if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) - ieee80211_if_sta_set_mesh_id(&sdata->u.sta, - params->mesh_id_len, - params->mesh_id); + ieee80211_sdata_set_mesh_id(sdata, + params->mesh_id_len, + params->mesh_id); if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) return 0; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8165df578c9..0fa7681a3d2 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -207,37 +207,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); #ifdef CONFIG_MAC80211_MESH /* Mesh stats attributes */ -IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC); -IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC); +IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); +IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); IEEE80211_IF_FILE(dropped_frames_no_route, - u.sta.mshstats.dropped_frames_no_route, DEC); -IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC); + u.mesh.mshstats.dropped_frames_no_route, DEC); +IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); /* Mesh parameters */ IEEE80211_IF_WFILE(dot11MeshMaxRetries, - u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8); + u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8); IEEE80211_IF_WFILE(dot11MeshRetryTimeout, - u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16); + u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16); IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, - u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16); + u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, - u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16); -IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8); -IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8); + u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16); +IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8); +IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8); IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, - u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); + u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, - u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); + u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, - u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); + u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, - u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); + u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, - u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); + u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); IEEE80211_IF_WFILE(path_refresh_time, - u.sta.mshcfg.path_refresh_time, DEC, u32); + u.mesh.mshcfg.path_refresh_time, DEC, u32); IEEE80211_IF_WFILE(min_discovery_timeout, - u.sta.mshcfg.min_discovery_timeout, DEC, u16); + u.mesh.mshcfg.min_discovery_timeout, DEC, u16); #endif @@ -350,7 +350,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) add_mesh_stats(sdata); add_mesh_config(sdata); #endif - /* fall through */ + break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: add_sta_files(sdata); @@ -487,7 +487,7 @@ static void del_files(struct ieee80211_sub_if_data *sdata) del_mesh_stats(sdata); del_mesh_config(sdata); #endif - /* fall through */ + break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: del_sta_files(sdata); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f334e4c3d6..cac0b133454 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -308,7 +308,6 @@ enum ieee80211_sta_mlme_state { IEEE80211_STA_MLME_ASSOCIATED, IEEE80211_STA_MLME_IBSS_SEARCH, IEEE80211_STA_MLME_IBSS_JOINED, - IEEE80211_STA_MLME_MESH_UP }; /* bitfield of allowed auth algs */ @@ -325,34 +324,6 @@ struct ieee80211_if_sta { size_t ssid_len; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; -#ifdef CONFIG_MAC80211_MESH - struct timer_list mesh_path_timer; - u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; - size_t mesh_id_len; - /* Active Path Selection Protocol Identifier */ - u8 mesh_pp_id[4]; - /* Active Path Selection Metric Identifier */ - u8 mesh_pm_id[4]; - /* Congestion Control Mode Identifier */ - u8 mesh_cc_id[4]; - /* Local mesh Destination Sequence Number */ - u32 dsn; - /* Last used PREQ ID */ - u32 preq_id; - atomic_t mpaths; - /* Timestamp of last DSN update */ - unsigned long last_dsn_update; - /* Timestamp of last DSN sent */ - unsigned long last_preq; - struct mesh_rmc *rmc; - spinlock_t mesh_preq_queue_lock; - struct mesh_preq_queue preq_queue; - int preq_queue_len; - struct mesh_stats mshstats; - struct mesh_config mshcfg; - u32 mesh_seqnum; - bool accepting_plinks; -#endif u16 aid; u16 ap_capab, capab; u8 *extra_ie; /* to be added to the end of AssocReq */ @@ -387,20 +358,47 @@ struct ieee80211_if_sta { int num_beacons; /* number of TXed beacon frames by this STA */ }; -static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta, - u8 mesh_id_len, u8 *mesh_id) -{ -#ifdef CONFIG_MAC80211_MESH - ifsta->mesh_id_len = mesh_id_len; - memcpy(ifsta->mesh_id, mesh_id, mesh_id_len); -#endif -} +struct ieee80211_if_mesh { + struct work_struct work; + struct timer_list housekeeping_timer; + struct timer_list mesh_path_timer; + struct sk_buff_head skb_queue; + + bool housekeeping; + + u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; + size_t mesh_id_len; + /* Active Path Selection Protocol Identifier */ + u8 mesh_pp_id[4]; + /* Active Path Selection Metric Identifier */ + u8 mesh_pm_id[4]; + /* Congestion Control Mode Identifier */ + u8 mesh_cc_id[4]; + /* Local mesh Destination Sequence Number */ + u32 dsn; + /* Last used PREQ ID */ + u32 preq_id; + atomic_t mpaths; + /* Timestamp of last DSN update */ + unsigned long last_dsn_update; + /* Timestamp of last DSN sent */ + unsigned long last_preq; + struct mesh_rmc *rmc; + spinlock_t mesh_preq_queue_lock; + struct mesh_preq_queue preq_queue; + int preq_queue_len; + struct mesh_stats mshstats; + struct mesh_config mshcfg; + u32 mesh_seqnum; + bool accepting_plinks; + int num_beacons; +}; #ifdef CONFIG_MAC80211_MESH -#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ - do { (sta)->mshstats.name++; } while (0) +#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ + do { (msh)->mshstats.name++; } while (0) #else -#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ +#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ do { } while (0) #endif @@ -455,6 +453,9 @@ struct ieee80211_sub_if_data { struct ieee80211_if_wds wds; struct ieee80211_if_vlan vlan; struct ieee80211_if_sta sta; +#ifdef CONFIG_MAC80211_MESH + struct ieee80211_if_mesh mesh; +#endif u32 mntr_flags; } u; @@ -548,6 +549,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) return container_of(p, struct ieee80211_sub_if_data, vif); } +static inline void +ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, + u8 mesh_id_len, u8 *mesh_id) +{ +#ifdef CONFIG_MAC80211_MESH + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + ifmsh->mesh_id_len = mesh_id_len; + memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); +#else + WARN_ON(1); +#endif +} + enum { IEEE80211_RX_MSG = 1, IEEE80211_TX_STATUS_MSG = 2, @@ -935,13 +949,6 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_sta_bss *bss); -#ifdef CONFIG_MAC80211_MESH -void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); -#else -static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) -{} -#endif - /* interface handling */ void ieee80211_if_setup(struct net_device *dev); int ieee80211_if_add(struct ieee80211_local *local, const char *name, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 672cec60a2f..ddbaa417e2e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -54,10 +54,9 @@ static void ieee80211_teardown_sdata(struct net_device *dev) break; case IEEE80211_IF_TYPE_MESH_POINT: - /* Allow compiler to elide mesh_rmc_free call. */ if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_rmc_free(sdata); - /* fall through */ + break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: kfree(sdata->u.sta.extra_ie); @@ -100,7 +99,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, skb_queue_head_init(&sdata->u.ap.ps_bc_buf); INIT_LIST_HEAD(&sdata->u.ap.vlans); break; - case IEEE80211_IF_TYPE_MESH_POINT: case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: ifsta = &sdata->u.sta; @@ -117,7 +115,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, IEEE80211_STA_AUTO_CHANNEL_SEL; if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) ifsta->flags |= IEEE80211_STA_WMM_ENABLED; - + break; + case IEEE80211_IF_TYPE_MESH_POINT: if (ieee80211_vif_is_mesh(&sdata->vif)) ieee80211_mesh_init_sdata(sdata); break; @@ -225,9 +224,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, if (ieee80211_vif_is_mesh(&sdata->vif) && params && params->mesh_id_len) - ieee80211_if_sta_set_mesh_id(&sdata->u.sta, - params->mesh_id_len, - params->mesh_id); + ieee80211_sdata_set_mesh_id(sdata, + params->mesh_id_len, + params->mesh_id); list_add_tail_rcu(&sdata->list, &local->interfaces); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6a7f4fae18c..522fe617648 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -252,6 +252,8 @@ static int ieee80211_open(struct net_device *dev) sdata->bss = &sdata->u.ap; break; case IEEE80211_IF_TYPE_MESH_POINT: + if (!ieee80211_vif_is_mesh(&sdata->vif)) + break; /* mesh ifaces must set allmulti to forward mcast traffic */ atomic_inc(&local->iff_allmultis); break; @@ -540,10 +542,6 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_configure_filter(local); netif_addr_unlock_bh(local->mdev); break; - case IEEE80211_IF_TYPE_MESH_POINT: - /* allmulti is always set on mesh ifaces */ - atomic_dec(&local->iff_allmultis); - /* fall through */ case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; @@ -571,6 +569,13 @@ static int ieee80211_stop(struct net_device *dev) sdata->u.sta.extra_ie = NULL; sdata->u.sta.extra_ie_len = 0; /* fall through */ + case IEEE80211_IF_TYPE_MESH_POINT: + if (ieee80211_vif_is_mesh(&sdata->vif)) { + /* allmulti is always set on mesh ifaces */ + atomic_dec(&local->iff_allmultis); + ieee80211_stop_mesh(sdata); + } + /* fall through */ default: conf.vif = &sdata->vif; conf.type = sdata->vif.type; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 3ccb3599c04..9e47725cc59 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -12,6 +12,9 @@ #include "ieee80211_i.h" #include "mesh.h" +#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) +#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) + #define PP_OFFSET 1 /* Path Selection Protocol */ #define PM_OFFSET 5 /* Path Selection Metric */ #define CC_OFFSET 9 /* Congestion Control Mode */ @@ -35,6 +38,16 @@ void ieee80211s_stop(void) kmem_cache_destroy(rm_cache); } +static void ieee80211_mesh_housekeeping_timer(unsigned long data) +{ + struct ieee80211_sub_if_data *sdata = (void *) data; + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + ifmsh->housekeeping = true; + queue_work(local->hw.workqueue, &ifmsh->work); +} + /** * mesh_matches_local - check if the config of a mesh point matches ours * @@ -46,7 +59,7 @@ void ieee80211s_stop(void) */ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *sta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; /* * As support for each feature is added, check for matching @@ -58,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat * - MDA enabled * - Power management control on fc */ - if (sta->mesh_id_len == ie->mesh_id_len && - memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && - memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && - memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && - memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) + if (ifmsh->mesh_id_len == ie->mesh_id_len && + memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && + memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && + memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && + memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) return true; return false; @@ -95,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) */ free_plinks = mesh_plink_availables(sdata); - if (free_plinks != sdata->u.sta.accepting_plinks) - ieee80211_sta_timer((unsigned long) sdata); + if (free_plinks != sdata->u.mesh.accepting_plinks) + ieee80211_mesh_housekeeping_timer((unsigned long) sdata); } -void mesh_ids_set_default(struct ieee80211_if_sta *sta) +void mesh_ids_set_default(struct ieee80211_if_mesh *sta) { u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; @@ -112,22 +125,22 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) { int i; - sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); - if (!sdata->u.sta.rmc) + sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); + if (!sdata->u.mesh.rmc) return -ENOMEM; - sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; + sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; for (i = 0; i < RMC_BUCKETS; i++) - INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); + INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); return 0; } void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) { - struct mesh_rmc *rmc = sdata->u.sta.rmc; + struct mesh_rmc *rmc = sdata->u.mesh.rmc; struct rmc_entry *p, *n; int i; - if (!sdata->u.sta.rmc) + if (!sdata->u.mesh.rmc) return; for (i = 0; i < RMC_BUCKETS; i++) @@ -137,7 +150,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) } kfree(rmc); - sdata->u.sta.rmc = NULL; + sdata->u.mesh.rmc = NULL; } /** @@ -155,7 +168,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, struct ieee80211_sub_if_data *sdata) { - struct mesh_rmc *rmc = sdata->u.sta.rmc; + struct mesh_rmc *rmc = sdata->u.mesh.rmc; u32 seqnum = 0; int entries = 0; u8 idx; @@ -217,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) } } - pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); + pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); *pos++ = WLAN_EID_MESH_ID; - *pos++ = sdata->u.sta.mesh_id_len; - if (sdata->u.sta.mesh_id_len) - memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len); + *pos++ = sdata->u.mesh.mesh_id_len; + if (sdata->u.mesh.mesh_id_len) + memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); pos = skb_put(skb, 21); *pos++ = WLAN_EID_MESH_CONFIG; @@ -230,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) *pos++ = 1; /* Active path selection protocol ID */ - memcpy(pos, sdata->u.sta.mesh_pp_id, 4); + memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); pos += 4; /* Active path selection metric ID */ - memcpy(pos, sdata->u.sta.mesh_pm_id, 4); + memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); pos += 4; /* Congestion control mode identifier */ - memcpy(pos, sdata->u.sta.mesh_cc_id, 4); + memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); pos += 4; /* Channel precedence: @@ -248,8 +261,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) pos += 4; /* Mesh capability */ - sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); - *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; + sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); + *pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00; *pos++ = 0x00; return; @@ -337,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_local *local = wdev_priv(&sdata->wdev); - queue_work(local->hw.workqueue, &ifsta->work); + queue_work(local->hw.workqueue, &ifmsh->work); } struct mesh_table *mesh_table_grow(struct mesh_table *tbl) @@ -392,50 +405,255 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, struct ieee80211_sub_if_data *sdata) { meshhdr->flags = 0; - meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; - put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); - sdata->u.sta.mesh_seqnum++; + meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; + put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); + sdata->u.mesh.mesh_seqnum++; return 6; } +static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_mesh *ifmsh) +{ + bool free_plinks; + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: running mesh housekeeping\n", + sdata->dev->name); +#endif + + ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); + mesh_path_expire(sdata); + + free_plinks = mesh_plink_availables(sdata); + if (free_plinks != sdata->u.mesh.accepting_plinks) + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); + + ifmsh->housekeeping = false; + mod_timer(&ifmsh->housekeeping_timer, + round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); +} + + +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_local *local = sdata->local; + + ifmsh->housekeeping = true; + queue_work(local->hw.workqueue, &ifmsh->work); + ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); +} + +void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) +{ + del_timer_sync(&sdata->u.mesh.housekeeping_timer); + /* + * When we get here, the interface is marked down. + * Call synchronize_rcu() to wait for the RX path + * should it be using the interface and enqueuing + * frames at this very time on another CPU. + */ + synchronize_rcu(); + skb_queue_purge(&sdata->u.mesh.skb_queue); +} + +static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + u16 stype, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_local *local= sdata->local; + struct ieee802_11_elems elems; + struct ieee80211_channel *channel; + u64 supp_rates = 0; + size_t baselen; + int freq; + enum ieee80211_band band = rx_status->band; + + /* ignore ProbeResp to foreign address */ + if (stype == IEEE80211_STYPE_PROBE_RESP && + compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) + return; + + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; + if (baselen > len) + return; + + ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, + &elems); + + if (elems.ds_params && elems.ds_params_len == 1) + freq = ieee80211_channel_to_frequency(elems.ds_params[0]); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(local->hw.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) + return; + + if (elems.mesh_id && elems.mesh_config && + mesh_matches_local(&elems, sdata)) { + supp_rates = ieee80211_sta_get_rates(local, &elems, band); + + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, + mesh_peer_accepts_plinks(&elems)); + } +} + +static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len, + struct ieee80211_rx_status *rx_status) +{ + switch (mgmt->u.action.category) { + case PLINK_CATEGORY: + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); + break; + case MESH_PATH_SEL_CATEGORY: + mesh_rx_path_sel_frame(sdata, mgmt, len); + break; + } +} + +static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status; + struct ieee80211_if_mesh *ifmsh; + struct ieee80211_mgmt *mgmt; + u16 stype; + + ifmsh = &sdata->u.mesh; + + rx_status = (struct ieee80211_rx_status *) skb->cb; + mgmt = (struct ieee80211_mgmt *) skb->data; + stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; + + switch (stype) { + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, + rx_status); + break; + case IEEE80211_STYPE_ACTION: + ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); + break; + } + + kfree_skb(skb); +} + +static void ieee80211_mesh_work(struct work_struct *work) +{ + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, u.mesh.work); + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct sk_buff *skb; + + if (!netif_running(sdata->dev)) + return; + + if (local->sta_sw_scanning || local->sta_hw_scanning) + return; + + while ((skb = skb_dequeue(&ifmsh->skb_queue))) + ieee80211_mesh_rx_queued_mgmt(sdata, skb); + + if (ifmsh->preq_queue_len && + time_after(jiffies, + ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) + mesh_path_start_discovery(sdata); + + if (ifmsh->housekeeping) + ieee80211_mesh_housekeeping(sdata, ifmsh); +} + +void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) + if (ieee80211_vif_is_mesh(&sdata->vif)) + queue_work(local->hw.workqueue, &sdata->u.mesh.work); + rcu_read_unlock(); +} + void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - - ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; - ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; - ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; - ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; - ifsta->mshcfg.dot11MeshTTL = MESH_TTL; - ifsta->mshcfg.auto_open_plinks = true; - ifsta->mshcfg.dot11MeshMaxPeerLinks = + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + + INIT_WORK(&ifmsh->work, ieee80211_mesh_work); + setup_timer(&ifmsh->housekeeping_timer, + ieee80211_mesh_housekeeping_timer, + (unsigned long) sdata); + skb_queue_head_init(&sdata->u.mesh.skb_queue); + + ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; + ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; + ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; + ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; + ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; + ifmsh->mshcfg.auto_open_plinks = true; + ifmsh->mshcfg.dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS; - ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = + ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT; - ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = + ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT; - ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = + ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME; - ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = + ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES; - ifsta->mshcfg.path_refresh_time = + ifmsh->mshcfg.path_refresh_time = MESH_PATH_REFRESH_TIME; - ifsta->mshcfg.min_discovery_timeout = + ifmsh->mshcfg.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT; - ifsta->accepting_plinks = true; - ifsta->preq_id = 0; - ifsta->dsn = 0; - atomic_set(&ifsta->mpaths, 0); + ifmsh->accepting_plinks = true; + ifmsh->preq_id = 0; + ifmsh->dsn = 0; + atomic_set(&ifmsh->mpaths, 0); mesh_rmc_init(sdata); - ifsta->last_preq = jiffies; + ifmsh->last_preq = jiffies; /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) ieee80211s_init(); - mesh_ids_set_default(ifsta); - setup_timer(&ifsta->mesh_path_timer, + mesh_ids_set_default(ifmsh); + setup_timer(&ifmsh->mesh_path_timer, ieee80211_mesh_path_timer, (unsigned long) sdata); - INIT_LIST_HEAD(&ifsta->preq_queue.list); - spin_lock_init(&ifsta->mesh_preq_queue_lock); + INIT_LIST_HEAD(&ifmsh->preq_queue.list); + spin_lock_init(&ifmsh->mesh_preq_queue_lock); +} + +ieee80211_rx_result +ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_mgmt *mgmt; + u16 fc; + + if (skb->len < 24) + return RX_DROP_MONITOR; + + mgmt = (struct ieee80211_mgmt *) skb->data; + fc = le16_to_cpu(mgmt->frame_control); + + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_BEACON: + case IEEE80211_STYPE_ACTION: + memcpy(skb->cb, rx_status, sizeof(*rx_status)); + skb_queue_tail(&ifmsh->skb_queue, skb); + queue_work(local->hw.workqueue, &ifmsh->work); + return RX_QUEUED; + } + + return RX_CONTINUE; } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 84ff5d828fd..8ee414a0447 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -206,7 +206,7 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, struct ieee80211_sub_if_data *sdata); bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata); -void mesh_ids_set_default(struct ieee80211_if_sta *sta); +void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); @@ -214,6 +214,11 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); void ieee80211s_init(void); void ieee80211s_stop(void); void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); +ieee80211_rx_result +ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status); +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); +void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); /* Mesh paths */ int mesh_nexthop_lookup(struct sk_buff *skb, @@ -269,8 +274,8 @@ extern int mesh_allocated; static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) { - return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks - - atomic_read(&sdata->u.sta.mshstats.estab_plinks); + return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - + atomic_read(&sdata->u.mesh.mshstats.estab_plinks); } static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) @@ -288,8 +293,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath) for (i = 0; i <= x->hash_mask; i++) \ hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) +void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); + #else #define mesh_allocated 0 +static inline void +ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} #endif #endif /* IEEE80211S_H */ diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 210d6b85240..1fad792ad25 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -64,14 +64,14 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) #define net_traversal_jiffies(s) \ - msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) + msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) #define default_lifetime(s) \ - MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout) + MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout) #define min_preq_int_jiff(s) \ - (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval)) -#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries) + (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval)) +#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries) #define disc_timeout_jiff(s) \ - msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout) + msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout) enum mpath_frame_type { MPATH_PREQ = 0, @@ -395,7 +395,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_path *mpath; u8 *dst_addr, *orig_addr; u8 dst_flags, ttl; @@ -414,11 +414,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, forward = false; reply = true; metric = 0; - if (time_after(jiffies, ifsta->last_dsn_update + + if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || - time_before(jiffies, ifsta->last_dsn_update)) { - dst_dsn = ++ifsta->dsn; - ifsta->last_dsn_update = jiffies; + time_before(jiffies, ifmsh->last_dsn_update)) { + dst_dsn = ++ifmsh->dsn; + ifmsh->last_dsn_update = jiffies; } } else { rcu_read_lock(); @@ -444,7 +444,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, if (reply) { lifetime = PREQ_IE_LIFETIME(preq_elem); - ttl = ifsta->mshcfg.dot11MeshTTL; + ttl = ifmsh->mshcfg.dot11MeshTTL; if (ttl != 0) mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, cpu_to_le32(dst_dsn), 0, orig_addr, @@ -452,7 +452,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, cpu_to_le32(lifetime), cpu_to_le32(metric), 0, sdata); else - ifsta->mshstats.dropped_frames_ttl++; + ifmsh->mshstats.dropped_frames_ttl++; } if (forward) { @@ -462,7 +462,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ttl = PREQ_IE_TTL(preq_elem); lifetime = PREQ_IE_LIFETIME(preq_elem); if (ttl <= 1) { - ifsta->mshstats.dropped_frames_ttl++; + ifmsh->mshstats.dropped_frames_ttl++; return; } --ttl; @@ -475,7 +475,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, hopcount, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), cpu_to_le32(preq_id), sdata); - ifsta->mshstats.fwded_frames++; + ifmsh->mshstats.fwded_frames++; } } @@ -503,7 +503,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, ttl = PREP_IE_TTL(prep_elem); if (ttl <= 1) { - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; return; } @@ -533,12 +533,12 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, cpu_to_le32(lifetime), cpu_to_le32(metric), 0, sdata); rcu_read_unlock(); - sdata->u.sta.mshstats.fwded_frames++; + sdata->u.mesh.mshstats.fwded_frames++; return; fail: rcu_read_unlock(); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; return; } @@ -631,7 +631,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) { struct ieee80211_sub_if_data *sdata = mpath->sdata; - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); @@ -640,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) return; } - spin_lock(&ifsta->mesh_preq_queue_lock); - if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { - spin_unlock(&ifsta->mesh_preq_queue_lock); + spin_lock(&ifmsh->mesh_preq_queue_lock); + if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { + spin_unlock(&ifmsh->mesh_preq_queue_lock); kfree(preq_node); if (printk_ratelimit()) printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); @@ -652,21 +652,21 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) memcpy(preq_node->dst, mpath->dst, ETH_ALEN); preq_node->flags = flags; - list_add_tail(&preq_node->list, &ifsta->preq_queue.list); - ++ifsta->preq_queue_len; - spin_unlock(&ifsta->mesh_preq_queue_lock); + list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); + ++ifmsh->preq_queue_len; + spin_unlock(&ifmsh->mesh_preq_queue_lock); - if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata))) - queue_work(sdata->local->hw.workqueue, &ifsta->work); + if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) + queue_work(sdata->local->hw.workqueue, &ifmsh->work); - else if (time_before(jiffies, ifsta->last_preq)) { + else if (time_before(jiffies, ifmsh->last_preq)) { /* avoid long wait if did not send preqs for a long time * and jiffies wrapped around */ - ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; - queue_work(sdata->local->hw.workqueue, &ifsta->work); + ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; + queue_work(sdata->local->hw.workqueue, &ifmsh->work); } else - mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + + mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + min_preq_int_jiff(sdata)); } @@ -677,25 +677,25 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) */ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; struct mesh_path *mpath; u8 ttl, dst_flags; u32 lifetime; - spin_lock(&ifsta->mesh_preq_queue_lock); - if (!ifsta->preq_queue_len || - time_before(jiffies, ifsta->last_preq + + spin_lock(&ifmsh->mesh_preq_queue_lock); + if (!ifmsh->preq_queue_len || + time_before(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) { - spin_unlock(&ifsta->mesh_preq_queue_lock); + spin_unlock(&ifmsh->mesh_preq_queue_lock); return; } - preq_node = list_first_entry(&ifsta->preq_queue.list, + preq_node = list_first_entry(&ifmsh->preq_queue.list, struct mesh_preq_queue, list); list_del(&preq_node->list); - --ifsta->preq_queue_len; - spin_unlock(&ifsta->mesh_preq_queue_lock); + --ifmsh->preq_queue_len; + spin_unlock(&ifmsh->mesh_preq_queue_lock); rcu_read_lock(); mpath = mesh_path_lookup(preq_node->dst, sdata); @@ -720,18 +720,18 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) goto enddiscovery; } - ifsta->last_preq = jiffies; + ifmsh->last_preq = jiffies; - if (time_after(jiffies, ifsta->last_dsn_update + + if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || - time_before(jiffies, ifsta->last_dsn_update)) { - ++ifsta->dsn; - sdata->u.sta.last_dsn_update = jiffies; + time_before(jiffies, ifmsh->last_dsn_update)) { + ++ifmsh->dsn; + sdata->u.mesh.last_dsn_update = jiffies; } lifetime = default_lifetime(sdata); - ttl = sdata->u.sta.mshcfg.dot11MeshTTL; + ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; if (ttl == 0) { - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } @@ -743,10 +743,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) spin_unlock_bh(&mpath->state_lock); mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, - cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, + cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, ttl, cpu_to_le32(lifetime), 0, - cpu_to_le32(ifsta->preq_id++), sdata); + cpu_to_le32(ifmsh->preq_id++), sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: @@ -783,7 +783,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { dev_kfree_skb(skb); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; err = -ENOSPC; goto endlookup; } @@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, mpath->exp_time - - msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) + msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0a60f55f32a..e4fa2905fad 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -153,7 +153,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) if (is_multicast_ether_addr(dst)) return -ENOTSUPP; - if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) + if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) return -ENOSPC; err = -ENOMEM; @@ -221,7 +221,7 @@ err_exists: err_node_alloc: kfree(new_mpath); err_path_alloc: - atomic_dec(&sdata->u.sta.mpaths); + atomic_dec(&sdata->u.mesh.mpaths); return err; } @@ -306,7 +306,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) struct ieee80211_sub_if_data *sdata = node->mpath->sdata; del_timer_sync(&node->mpath->timer); - atomic_dec(&sdata->u.sta.mpaths); + atomic_dec(&sdata->u.mesh.mpaths); kfree(node->mpath); kfree(node); } @@ -401,7 +401,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, } kfree_skb(skb); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; } /** diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7356462dee9..990a4b7f6bc 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -36,11 +36,11 @@ #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 #define MESH_SECURITY_FAILED_VERIFICATION 10 -#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries) -#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout) -#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout) -#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout) -#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks) +#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) +#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) +#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) +#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) +#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) enum plink_frame_type { PLINK_OPEN = 0, @@ -63,14 +63,14 @@ enum plink_event { static inline void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { - atomic_inc(&sdata->u.sta.mshstats.estab_plinks); + atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); mesh_accept_plinks_update(sdata); } static inline void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) { - atomic_dec(&sdata->u.sta.mshstats.estab_plinks); + atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); mesh_accept_plinks_update(sdata); } @@ -245,8 +245,8 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data sta->last_rx = jiffies; sta->supp_rates[local->hw.conf.channel->band] = rates; if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && - sdata->u.sta.accepting_plinks && - sdata->u.sta.mshcfg.auto_open_plinks) + sdata->u.mesh.accepting_plinks && + sdata->u.mesh.mshcfg.auto_open_plinks) mesh_plink_open(sta); rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ef73f895372..9e20a0c20a4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -22,11 +22,11 @@ #include #include #include +#include #include "ieee80211_i.h" #include "rate.h" #include "led.h" -#include "mesh.h" #define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 #define IEEE80211_AUTH_TIMEOUT (HZ / 5) @@ -34,7 +34,6 @@ #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) #define IEEE80211_ASSOC_MAX_TRIES 3 #define IEEE80211_MONITORING_INTERVAL (2 * HZ) -#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) #define IEEE80211_PROBE_INTERVAL (60 * HZ) #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) #define IEEE80211_SCAN_INTERVAL (2 * HZ) @@ -43,7 +42,6 @@ #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) -#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 @@ -1508,14 +1506,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) return; - if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && - elems->mesh_config && mesh_matches_local(elems, sdata)) { - supp_rates = ieee80211_sta_get_rates(local, elems, band); - - mesh_neighbour_update(mgmt->sa, supp_rates, sdata, - mesh_peer_accepts_plinks(elems)); - } - if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { supp_rates = ieee80211_sta_get_rates(local, elems, band); @@ -1785,26 +1775,6 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, ieee80211_tx_skb(sdata, skb, 0); } -static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - /* currently we only handle mesh interface action frames here */ - if (!ieee80211_vif_is_mesh(&sdata->vif)) - return; - - switch (mgmt->u.action.category) { - case PLINK_CATEGORY: - mesh_rx_plink_frame(sdata, mgmt, len, rx_status); - break; - case MESH_PATH_SEL_CATEGORY: - mesh_rx_path_sel_frame(sdata, mgmt, len); - break; - } -} - void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { @@ -1825,7 +1795,6 @@ void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff * case IEEE80211_STYPE_PROBE_REQ: case IEEE80211_STYPE_PROBE_RESP: case IEEE80211_STYPE_BEACON: - case IEEE80211_STYPE_ACTION: memcpy(skb->cb, rx_status, sizeof(*rx_status)); case IEEE80211_STYPE_AUTH: case IEEE80211_STYPE_ASSOC_RESP: @@ -1881,9 +1850,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, case IEEE80211_STYPE_DISASSOC: ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); break; - case IEEE80211_STYPE_ACTION: - ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status); - break; } kfree_skb(skb); @@ -1928,35 +1894,6 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, } -#ifdef CONFIG_MAC80211_MESH -static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_sta *ifsta) -{ - bool free_plinks; - - ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); - mesh_path_expire(sdata); - - free_plinks = mesh_plink_availables(sdata); - if (free_plinks != sdata->u.sta.accepting_plinks) - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); - - mod_timer(&ifsta->timer, jiffies + - IEEE80211_MESH_HOUSEKEEPING_INTERVAL); -} - - -void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_sta *ifsta; - ifsta = &sdata->u.sta; - ifsta->state = IEEE80211_STA_MLME_MESH_UP; - ieee80211_sta_timer((unsigned long)sdata); - ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); -} -#endif - - void ieee80211_sta_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata = @@ -2524,21 +2461,13 @@ void ieee80211_sta_work(struct work_struct *work) return; if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) + sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) return; ifsta = &sdata->u.sta; while ((skb = skb_dequeue(&ifsta->skb_queue))) ieee80211_sta_rx_queued_mgmt(sdata, skb); -#ifdef CONFIG_MAC80211_MESH - if (ifsta->preq_queue_len && - time_after(jiffies, - ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) - mesh_path_start_discovery(sdata); -#endif - if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && @@ -2575,11 +2504,6 @@ void ieee80211_sta_work(struct work_struct *work) case IEEE80211_STA_MLME_IBSS_JOINED: ieee80211_sta_merge_ibss(sdata, ifsta); break; -#ifdef CONFIG_MAC80211_MESH - case IEEE80211_STA_MLME_MESH_UP: - ieee80211_mesh_housekeeping(sdata, ifsta); - break; -#endif default: WARN_ON(1); break; @@ -2596,8 +2520,7 @@ void ieee80211_sta_work(struct work_struct *work) static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) { - if (sdata->vif.type == IEEE80211_IF_TYPE_STA || - ieee80211_vif_is_mesh(&sdata->vif)) + if (sdata->vif.type == IEEE80211_IF_TYPE_STA) queue_work(sdata->local->hw.workqueue, &sdata->u.sta.work); } diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a914ba73ccf..21e1942ea97 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -148,9 +148,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, struct ieee80211_local *local, struct sta_info *sta) { -#ifdef CONFIG_MAC80211_MESH struct ieee80211_sub_if_data *sdata = sta->sdata; -#endif struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; struct rc_pid_rateinfo *rinfo = pinfo->rinfo; struct ieee80211_supported_band *sband; @@ -181,11 +179,8 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, pf = spinfo->last_pf; else { pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; -#ifdef CONFIG_MAC80211_MESH - if (pf == 100 && - sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) + if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) mesh_plink_broken(sta); -#endif pf <<= RC_PID_ARITH_SHIFT; sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) >> RC_PID_ARITH_SHIFT; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d0803797902..208563a27bc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1404,7 +1404,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (rx->flags & IEEE80211_RX_RA_MATCH) { if (!mesh_hdr->ttl) - IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, + IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, dropped_frames_ttl); else { struct ieee80211_hdr *fwd_hdr; @@ -1591,9 +1591,11 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; + if (ieee80211_vif_is_mesh(&sdata->vif)) + return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); + if (sdata->vif.type != IEEE80211_IF_TYPE_STA && - sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) + sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return RX_DROP_MONITOR; if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f8b296bed0b..f4399e9ac92 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -476,6 +476,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) done: ieee80211_mlme_notify_scan_completed(local); + ieee80211_mesh_notify_scan_completed(local); } EXPORT_SYMBOL(ieee80211_scan_completed); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c413d4836af..1059b17c83b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1330,7 +1330,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (mesh_nexthop_lookup(skb, osdata)) return 0; if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) - IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, + IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, fwded_frames); } } @@ -1483,9 +1483,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); - if (!sdata->u.sta.mshcfg.dot11MeshTTL) { + if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { /* Do not send frames with mesh_ttl == 0 */ - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; ret = 0; goto fail; } @@ -1815,10 +1815,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct rate_selection rsel; struct beacon_data *beacon; struct ieee80211_supported_band *sband; - struct ieee80211_mgmt *mgmt; int *num_beacons; enum ieee80211_band band = local->hw.conf.channel->band; - u8 *pos; sband = local->hw.wiphy->bands[band]; @@ -1885,7 +1883,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, IEEE80211_STYPE_BEACON); num_beacons = &ifsta->num_beacons; +#ifdef CONFIG_MAC80211_MESH } else if (ieee80211_vif_is_mesh(&sdata->vif)) { + struct ieee80211_mgmt *mgmt; + u8 *pos; + /* headroom, head length, tail length and maximum TIM length */ skb = dev_alloc_skb(local->tx_headroom + 400); if (!skb) @@ -1910,7 +1912,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, mesh_mgmt_ies_add(skb, sdata); - num_beacons = &sdata->u.sta.num_beacons; + num_beacons = &sdata->u.mesh.num_beacons; +#endif } else { WARN_ON(1); goto out; -- cgit v1.2.3-70-g09d2 From b7413430d4d2a6168e68231d9f93763047b6d60c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:50 +0200 Subject: mac80211: fix work race When we stop an interface, the work on it may still be pending or running. We do cancel the timer, but we do not currently protect against the work struct. The race is very unlikely to hit -- it'll happen only when the driver is using mac80211's workqueue to run long-running tasks and the sta/mesh works are delayed for quite a bit. This patch fixes it by cancelling the work explicitly. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/main.c | 8 ++++++++ net/mac80211/mesh.c | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 522fe617648..ebdec7106d6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -547,6 +547,14 @@ static int ieee80211_stop(struct net_device *dev) sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; memset(sdata->u.sta.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.sta.timer); + /* + * If the timer fired while we waited for it, it will have + * requeued the work. Now the work will be running again + * but will not rearm the timer again because it checks + * whether the interface is running, which, at this point, + * it no longer is. + */ + cancel_work_sync(&sdata->u.sta.work); /* * When we get here, the interface is marked down. * Call synchronize_rcu() to wait for the RX path diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 9e47725cc59..a0141f5ff18 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -448,6 +448,15 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) { del_timer_sync(&sdata->u.mesh.housekeeping_timer); + /* + * If the timer fired while we waited for it, it will have + * requeued the work. Now the work will be running again + * but will not rearm the timer again because it checks + * whether the interface is running, which, at this point, + * it no longer is. + */ + cancel_work_sync(&sdata->u.mesh.work); + /* * When we get here, the interface is marked down. * Call synchronize_rcu() to wait for the RX path -- cgit v1.2.3-70-g09d2 From c2b13452b283f9c4a5b02a6b53ed6416ebf4c03c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 11 Sep 2008 00:01:55 +0200 Subject: mac80211: clean up scan namespace Most of the scan functions are called ieee80211_sta_scan_* or similar, make clean it up so they are all just called ieee80211_scan_*. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 53 ++++++++-------- net/mac80211/main.c | 6 +- net/mac80211/mesh.c | 2 +- net/mac80211/mlme.c | 51 +++++++-------- net/mac80211/rx.c | 10 +-- net/mac80211/scan.c | 153 +++++++++++++++++++++++---------------------- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 2 +- net/mac80211/wext.c | 6 +- 9 files changed, 145 insertions(+), 140 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 52f36ab1ee5..5c38ea08454 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -71,9 +71,9 @@ struct ieee80211_fragment_entry { }; -struct ieee80211_sta_bss { +struct ieee80211_bss { struct list_head list; - struct ieee80211_sta_bss *hnext; + struct ieee80211_bss *hnext; size_t ssid_len; atomic_t users; @@ -112,7 +112,7 @@ struct ieee80211_sta_bss { u8 erp_value; }; -static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) +static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) { #ifdef CONFIG_MAC80211_MESH return bss->mesh_cfg; @@ -120,7 +120,7 @@ static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) return NULL; } -static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) +static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) { #ifdef CONFIG_MAC80211_MESH return bss->mesh_id; @@ -128,7 +128,7 @@ static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) return NULL; } -static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss) +static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) { #ifdef CONFIG_MAC80211_MESH return bss->mesh_id_len; @@ -658,8 +658,8 @@ struct ieee80211_local { spinlock_t key_lock; - bool sta_sw_scanning; - bool sta_hw_scanning; + /* Scanning and BSS list */ + bool sw_scanning, hw_scanning; int scan_channel_idx; enum ieee80211_band scan_band; @@ -670,9 +670,9 @@ struct ieee80211_local { struct ieee80211_channel *oper_channel, *scan_channel; u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; size_t scan_ssid_len; - struct list_head sta_bss_list; - struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE]; - spinlock_t sta_bss_lock; + struct list_head bss_list; + struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; + spinlock_t bss_lock; /* SNMP counters */ /* dot11CountersTable */ @@ -905,7 +905,7 @@ extern const struct iw_handler_def ieee80211_iw_handler_def; /* STA/IBSS code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); -void ieee80211_sta_scan_work(struct work_struct *work); +void ieee80211_scan_work(struct work_struct *work); void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); @@ -926,35 +926,38 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); /* scan/BSS handling */ -int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); -int ieee80211_sta_scan_results(struct ieee80211_local *local, - struct iw_request_info *info, - char *buf, size_t len); -ieee80211_rx_result ieee80211_sta_rx_scan( - struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status); +int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + u8 *ssid, size_t ssid_len); +int ieee80211_scan_results(struct ieee80211_local *local, + struct iw_request_info *info, + char *buf, size_t len); +ieee80211_rx_result +ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_rx_status *rx_status); void ieee80211_rx_bss_list_init(struct ieee80211_local *local); void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); -int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len); +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, + char *ie, size_t len); void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); -int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, - u8 *ssid, size_t ssid_len); -struct ieee80211_sta_bss * +int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, + u8 *ssid, size_t ssid_len); +struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, struct ieee80211_mgmt *mgmt, size_t len, struct ieee802_11_elems *elems, int freq, bool beacon); -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss); + struct ieee80211_bss *bss); /* interface handling */ void ieee80211_if_setup(struct net_device *dev); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 72e3f5574e9..4c424acc01a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -598,7 +598,7 @@ static int ieee80211_stop(struct net_device *dev) * the scan_sdata is NULL already don't send out a * scan event to userspace -- the scan is incomplete. */ - if (local->sta_sw_scanning) + if (local->sw_scanning) ieee80211_scan_completed(&local->hw); } @@ -732,7 +732,7 @@ int ieee80211_hw_config(struct ieee80211_local *local) struct ieee80211_channel *chan; int ret = 0; - if (local->sta_sw_scanning) + if (local->sw_scanning) chan = local->scan_channel; else chan = local->oper_channel; @@ -1290,7 +1290,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, spin_lock_init(&local->key_lock); - INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); + INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); sta_info_init(local); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a0141f5ff18..30cf891fd3a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -566,7 +566,7 @@ static void ieee80211_mesh_work(struct work_struct *work) if (!netif_running(sdata->dev)) return; - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) return; while ((skb = skb_dequeue(&ifmsh->skb_queue))) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e1483010652..5b748447eb7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -52,7 +52,7 @@ static int ecw2cw(int ecw) return (1 << ecw) - 1; } -static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) +static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) { u8 *end, *pos; @@ -72,7 +72,7 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) return NULL; } -static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, +static int ieee80211_compatible_rates(struct ieee80211_bss *bss, struct ieee80211_supported_band *sband, u64 *rates) { @@ -239,7 +239,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, u8 *pos, *ies, *ht_add_ie; int i, len, count, rates_len, supp_rates_len; u16 capab; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; u64 rates = 0; @@ -470,7 +470,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, /* MLME */ static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; @@ -621,7 +621,7 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, } static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { u32 changed = 0; @@ -674,7 +674,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_conf *conf = &local_to_hw(local)->conf; u32 changed = BSS_CHANGED_ASSOC; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; ifsta->flags |= IEEE80211_STA_ASSOCIATED; @@ -846,7 +846,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int bss_privacy; int wep_privacy; int privacy_invoked; @@ -1219,7 +1219,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, /* Add STA entry for the AP */ sta = sta_info_get(local, ifsta->bssid); if (!sta) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int err; sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); @@ -1339,7 +1339,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { struct ieee80211_local *local = sdata->local; int res, rates, i, j; @@ -1490,7 +1490,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; int freq; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; struct sta_info *sta; struct ieee80211_channel *channel; u64 beacon_timestamp, rx_timestamp; @@ -1893,7 +1893,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->dev->name); - ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); + ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); } @@ -1974,7 +1974,7 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN], *pos; int i; @@ -2035,7 +2035,7 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int found = 0; u8 bssid[ETH_ALEN]; int active_ibss; @@ -2050,8 +2050,8 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", sdata->dev->name, active_ibss); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - spin_lock_bh(&local->sta_bss_lock); - list_for_each_entry(bss, &local->sta_bss_list, list) { + spin_lock_bh(&local->bss_lock); + list_for_each_entry(bss, &local->bss_list, list) { if (ifsta->ssid_len != bss->ssid_len || memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 || !(bss->capability & WLAN_CAPABILITY_IBSS)) @@ -2065,7 +2065,7 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) break; } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); #ifdef CONFIG_MAC80211_IBSS_DEBUG if (found) @@ -2110,7 +2110,7 @@ dont_join: IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->dev->name); - return ieee80211_sta_req_scan(sdata, ifsta->ssid, + return ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; @@ -2145,12 +2145,12 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sta_bss *bss, *selected = NULL; + struct ieee80211_bss *bss, *selected = NULL; int top_rssi = 0, freq; - spin_lock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); freq = local->oper_channel->center_freq; - list_for_each_entry(bss, &local->sta_bss_list, list) { + list_for_each_entry(bss, &local->bss_list, list) { if (!(bss->capability & WLAN_CAPABILITY_ESS)) continue; @@ -2180,7 +2180,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, } if (selected) atomic_inc(&selected->users); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); if (selected) { ieee80211_set_freq(sdata, selected->freq); @@ -2207,9 +2207,9 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { ifsta->assoc_scan_tries++; if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(sdata, NULL, 0); + ieee80211_start_scan(sdata, NULL, 0); else - ieee80211_sta_start_scan(sdata, ifsta->ssid, + ieee80211_start_scan(sdata, ifsta->ssid, ifsta->ssid_len); ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); @@ -2231,7 +2231,7 @@ static void ieee80211_sta_work(struct work_struct *work) if (!netif_running(sdata->dev)) return; - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) return; if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && @@ -2246,7 +2246,8 @@ static void ieee80211_sta_work(struct work_struct *work) ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { - ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); + ieee80211_start_scan(sdata, ifsta->scan_ssid, + ifsta->scan_ssid_len); return; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 93f2cda9926..582396a4fdb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -403,12 +403,12 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) struct ieee80211_local *local = rx->local; struct sk_buff *skb = rx->skb; - if (unlikely(local->sta_hw_scanning)) - return ieee80211_sta_rx_scan(rx->sdata, skb, rx->status); + if (unlikely(local->hw_scanning)) + return ieee80211_scan_rx(rx->sdata, skb, rx->status); - if (unlikely(local->sta_sw_scanning)) { + if (unlikely(local->sw_scanning)) { /* drop all the other packets during a software scan anyway */ - if (ieee80211_sta_rx_scan(rx->sdata, skb, rx->status) + if (ieee80211_scan_rx(rx->sdata, skb, rx->status) != RX_QUEUED) dev_kfree_skb(skb); return RX_QUEUED; @@ -1918,7 +1918,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, return; } - if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning)) + if (unlikely(local->sw_scanning || local->hw_scanning)) rx.flags |= IEEE80211_RX_IN_SCAN; ieee80211_parse_qos(&rx); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 27727027d76..5e719e7b720 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -32,26 +32,26 @@ void ieee80211_rx_bss_list_init(struct ieee80211_local *local) { - spin_lock_init(&local->sta_bss_lock); - INIT_LIST_HEAD(&local->sta_bss_list); + spin_lock_init(&local->bss_lock); + INIT_LIST_HEAD(&local->bss_list); } void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) { - struct ieee80211_sta_bss *bss, *tmp; + struct ieee80211_bss *bss, *tmp; - list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) + list_for_each_entry_safe(bss, tmp, &local->bss_list, list) ieee80211_rx_bss_put(local, bss); } -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[STA_HASH(bssid)]; + spin_lock_bh(&local->bss_lock); + bss = local->bss_hash[STA_HASH(bssid)]; while (bss) { if (!bss_mesh_cfg(bss) && !memcmp(bss->bssid, bssid, ETH_ALEN) && @@ -63,13 +63,13 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, } bss = bss->hnext; } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } -/* Caller must hold local->sta_bss_lock */ +/* Caller must hold local->bss_lock */ static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { u8 hash_idx; @@ -79,20 +79,20 @@ static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, else hash_idx = STA_HASH(bss->bssid); - bss->hnext = local->sta_bss_hash[hash_idx]; - local->sta_bss_hash[hash_idx] = bss; + bss->hnext = local->bss_hash[hash_idx]; + local->bss_hash[hash_idx] = bss; } -/* Caller must hold local->sta_bss_lock */ +/* Caller must hold local->bss_lock */ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { - struct ieee80211_sta_bss *b, *prev = NULL; - b = local->sta_bss_hash[STA_HASH(bss->bssid)]; + struct ieee80211_bss *b, *prev = NULL; + b = local->bss_hash[STA_HASH(bss->bssid)]; while (b) { if (b == bss) { if (!prev) - local->sta_bss_hash[STA_HASH(bss->bssid)] = + local->bss_hash[STA_HASH(bss->bssid)] = bss->hnext; else prev->hnext = bss->hnext; @@ -103,11 +103,11 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, } } -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); if (!bss) @@ -120,23 +120,23 @@ ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, bss->ssid_len = ssid_len; } - spin_lock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); + list_add_tail(&bss->list, &local->bss_list); __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } #ifdef CONFIG_MAC80211_MESH -static struct ieee80211_sta_bss * +static struct ieee80211_bss * ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int freq) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; - spin_lock_bh(&local->sta_bss_lock); - bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; + spin_lock_bh(&local->bss_lock); + bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; while (bss) { if (bss_mesh_cfg(bss) && !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && @@ -149,15 +149,15 @@ ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_i } bss = bss->hnext; } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } -static struct ieee80211_sta_bss * +static struct ieee80211_bss * ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int mesh_config_len, int freq) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; if (mesh_config_len != MESH_CFG_LEN) return NULL; @@ -186,16 +186,16 @@ ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_i memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); bss->mesh_id_len = mesh_id_len; bss->freq = freq; - spin_lock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); /* TODO: order by RSSI? */ - list_add_tail(&bss->list, &local->sta_bss_list); + list_add_tail(&bss->list, &local->bss_list); __ieee80211_rx_bss_hash_add(local, bss); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return bss; } #endif -static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) +static void ieee80211_rx_bss_free(struct ieee80211_bss *bss) { kfree(bss->ies); kfree(bss_mesh_id(bss)); @@ -204,21 +204,21 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) } void ieee80211_rx_bss_put(struct ieee80211_local *local, - struct ieee80211_sta_bss *bss) + struct ieee80211_bss *bss) { local_bh_disable(); - if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { + if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) { local_bh_enable(); return; } __ieee80211_rx_bss_hash_del(local, bss); list_del(&bss->list); - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); ieee80211_rx_bss_free(bss); } -struct ieee80211_sta_bss * +struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, struct ieee80211_mgmt *mgmt, @@ -226,7 +226,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee802_11_elems *elems, int freq, bool beacon) { - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; int clen; #ifdef CONFIG_MAC80211_MESH @@ -252,9 +252,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local, } else { #if 0 /* TODO: order by RSSI? */ - spin_lock_bh(&local->sta_bss_lock); - list_move_tail(&bss->list, &local->sta_bss_list); - spin_unlock_bh(&local->sta_bss_lock); + spin_lock_bh(&local->bss_lock); + list_move_tail(&bss->list, &local->bss_list); + spin_unlock_bh(&local->bss_lock); #endif } @@ -327,11 +327,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local, } ieee80211_rx_result -ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status) +ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) { struct ieee80211_mgmt *mgmt; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; u8 *elements; struct ieee80211_channel *channel; size_t baselen; @@ -430,7 +430,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) struct ieee80211_sub_if_data *sdata; union iwreq_data wrqu; - if (WARN_ON(!local->sta_hw_scanning && !local->sta_sw_scanning)) + if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) return; local->last_scan_completed = jiffies; @@ -445,8 +445,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) if (sdata) wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); - if (local->sta_hw_scanning) { - local->sta_hw_scanning = 0; + if (local->hw_scanning) { + local->hw_scanning = false; if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " "channel after scan\n", wiphy_name(local->hw.wiphy)); @@ -454,7 +454,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) goto done; } - local->sta_sw_scanning = 0; + local->sw_scanning = false; if (ieee80211_hw_config(local)) printk(KERN_DEBUG "%s: failed to restore operational " "channel after scan\n", wiphy_name(local->hw.wiphy)); @@ -492,7 +492,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) EXPORT_SYMBOL(ieee80211_scan_completed); -void ieee80211_sta_scan_work(struct work_struct *work) +void ieee80211_scan_work(struct work_struct *work) { struct ieee80211_local *local = container_of(work, struct ieee80211_local, scan_work.work); @@ -589,8 +589,8 @@ void ieee80211_sta_scan_work(struct work_struct *work) } -int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, - u8 *ssid, size_t ssid_len) +int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, + u8 *ssid, size_t ssid_len) { struct ieee80211_local *local = scan_sdata->local; struct ieee80211_sub_if_data *sdata; @@ -615,7 +615,7 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, * ResultCode: SUCCESS, INVALID_PARAMETERS */ - if (local->sta_sw_scanning || local->sta_hw_scanning) { + if (local->sw_scanning || local->hw_scanning) { if (local->scan_sdata == scan_sdata) return 0; return -EBUSY; @@ -624,17 +624,17 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, if (local->ops->hw_scan) { int rc; - local->sta_hw_scanning = 1; + local->hw_scanning = true; rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); if (rc) { - local->sta_hw_scanning = 0; + local->hw_scanning = false; return rc; } local->scan_sdata = scan_sdata; return 0; } - local->sta_sw_scanning = 1; + local->sw_scanning = true; rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { @@ -675,13 +675,14 @@ int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, } -int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) +int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + u8 *ssid, size_t ssid_len) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return ieee80211_sta_start_scan(sdata, ssid, ssid_len); + return ieee80211_start_scan(sdata, ssid, ssid_len); /* * STA has a state machine that might need to defer scanning @@ -689,7 +690,7 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t * queue it up to the state machine in that case. */ - if (local->sta_sw_scanning || local->sta_hw_scanning) { + if (local->sw_scanning || local->hw_scanning) { if (local->scan_sdata == sdata) return 0; return -EBUSY; @@ -707,9 +708,9 @@ int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t } -static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, - struct ieee80211_sta_bss *bss, - char **current_ev, char *end_buf) +static void ieee80211_scan_add_ies(struct iw_request_info *info, + struct ieee80211_bss *bss, + char **current_ev, char *end_buf) { u8 *pos, *end, *next; struct iw_event iwe; @@ -749,10 +750,10 @@ static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, static char * -ieee80211_sta_scan_result(struct ieee80211_local *local, - struct iw_request_info *info, - struct ieee80211_sta_bss *bss, - char *current_ev, char *end_buf) +ieee80211_scan_result(struct ieee80211_local *local, + struct iw_request_info *info, + struct ieee80211_bss *bss, + char *current_ev, char *end_buf) { struct iw_event iwe; char *buf; @@ -828,7 +829,7 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); - ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); + ieee80211_scan_add_ies(info, bss, ¤t_ev, end_buf); if (bss->supp_rates_len > 0) { /* display all supported rates in readable format */ @@ -914,23 +915,23 @@ ieee80211_sta_scan_result(struct ieee80211_local *local, } -int ieee80211_sta_scan_results(struct ieee80211_local *local, - struct iw_request_info *info, - char *buf, size_t len) +int ieee80211_scan_results(struct ieee80211_local *local, + struct iw_request_info *info, + char *buf, size_t len) { char *current_ev = buf; char *end_buf = buf + len; - struct ieee80211_sta_bss *bss; + struct ieee80211_bss *bss; - spin_lock_bh(&local->sta_bss_lock); - list_for_each_entry(bss, &local->sta_bss_list, list) { + spin_lock_bh(&local->bss_lock); + list_for_each_entry(bss, &local->bss_list, list) { if (buf + len - current_ev <= IW_EV_ADDR_LEN) { - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return -E2BIG; } - current_ev = ieee80211_sta_scan_result(local, info, bss, + current_ev = ieee80211_scan_result(local, info, bss, current_ev, end_buf); } - spin_unlock_bh(&local->sta_bss_lock); + spin_unlock_bh(&local->bss_lock); return current_ev - buf; } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1059b17c83b..e606ba08ddd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -222,7 +222,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) return TX_CONTINUE; - if (unlikely(tx->local->sta_sw_scanning) && + if (unlikely(tx->local->sw_scanning) && !ieee80211_is_probe_req(hdr->frame_control)) return TX_DROP; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cf0b820a0ea..a7968df9dac 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -630,7 +630,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) } local->oper_channel = chan; - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) ret = 0; else ret = ieee80211_hw_config(local); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 97d132811c8..77b68ed8b83 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -552,7 +552,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, ssid_len = req->essid_len; } - return ieee80211_sta_req_scan(sdata, ssid, ssid_len); + return ieee80211_request_scan(sdata, ssid, ssid_len); } @@ -566,10 +566,10 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (local->sta_sw_scanning || local->sta_hw_scanning) + if (local->sw_scanning || local->hw_scanning) return -EAGAIN; - res = ieee80211_sta_scan_results(local, info, extra, data->length); + res = ieee80211_scan_results(local, info, extra, data->length); if (res >= 0) { data->length = res; return 0; -- cgit v1.2.3-70-g09d2 From 133b822638ff01eb1e32e1917b197c40ed095ddd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Sep 2008 14:18:59 +0200 Subject: mac80211: make master iface not wireless There's no need to register the master netdev with cfg80211, in fact, this is quite dangerous and lead to having to add checks for the master interface all over the config handlers. This patch removes the "ieee80211_ptr" from the master iface in favour of having a small netdev_priv() associated with the master interface that stores the ieee80211_local pointer. Because of this, a lot of code in the configuration handlers can go away. To make this patch easier to verify I have also removed a number of wiphy_priv() calls in favour of getting the sdata first and then the local pointer from that. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 59 ---------------------------------------------- net/mac80211/debugfs_sta.c | 3 +-- net/mac80211/ieee80211_i.h | 4 ++++ net/mac80211/main.c | 19 ++++++++------- net/mac80211/mesh.c | 2 +- net/mac80211/rx.c | 25 ++++++++------------ net/mac80211/tx.c | 26 ++++++++++---------- 7 files changed, 39 insertions(+), 99 deletions(-) (limited to 'net/mac80211/mesh.c') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e2574885db4..a8501f14b16 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct net_device *dev; struct ieee80211_sub_if_data *sdata; int ret; @@ -95,9 +94,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, if (!nl80211_type_check(type)) return -EINVAL; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ret = ieee80211_if_change_type(sdata, type); @@ -120,16 +116,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, u8 *mac_addr, struct key_params *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; enum ieee80211_key_alg alg; struct ieee80211_key *key; int err; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); switch (params->cipher) { @@ -174,14 +166,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, u8 *mac_addr) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; int ret; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -222,7 +210,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, void (*callback)(void *cookie, struct key_params *params)) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct sta_info *sta = NULL; u8 seq[6] = {0}; @@ -232,9 +219,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, u16 iv16; int err = -ENOENT; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -310,12 +294,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; - if (dev == local->mdev) - return -EOPNOTSUPP; - rcu_read_lock(); sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -496,13 +476,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -519,13 +495,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -541,13 +513,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) @@ -695,9 +663,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; int err; - if (dev == local->mdev || params->vlan == local->mdev) - return -EOPNOTSUPP; - /* Prevent a race with changing the rate control algorithm */ if (!netif_running(dev)) return -ENETDOWN; @@ -752,9 +717,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (mac) { @@ -786,9 +748,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; - if (dev == local->mdev || params->vlan == local->mdev) - return -EOPNOTSUPP; - rcu_read_lock(); /* XXX: get sta belonging to dev */ @@ -828,9 +787,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, struct sta_info *sta; int err; - if (dev == local->mdev) - return -EOPNOTSUPP; - if (!netif_running(dev)) return -ENETDOWN; @@ -884,9 +840,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, struct mesh_path *mpath; struct sta_info *sta; - if (dev == local->mdev) - return -EOPNOTSUPP; - if (!netif_running(dev)) return -ENETDOWN; @@ -958,13 +911,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -986,13 +935,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) @@ -1015,13 +960,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; u32 changed = 0; - if (dev == local->mdev) - return -EOPNOTSUPP; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != NL80211_IFTYPE_AP) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 81f350eaf8a..b9902e425f0 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct sta_info *sta = file->private_data; - struct net_device *dev = sta->sdata->dev; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sta->sdata->local; struct ieee80211_hw *hw = &local->hw; u8 *da = sta->sta.addr; static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3912fba6d3d..0b25b0f46b1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -573,6 +573,10 @@ enum { /* maximum number of hardware queues we support. */ #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) +struct ieee80211_master_priv { + struct ieee80211_local *local; +}; + struct ieee80211_local { /* embed the driver visible part. * don't cast (use the static inlines below), but we keep diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c307dba7ec0..7d2d5a041e2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = { static int ieee80211_master_open(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_sub_if_data *sdata; int res = -EOPNOTSUPP; @@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) static int ieee80211_master_stop(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_sub_if_data *sdata; /* we hold the RTNL here so can safely walk the list */ @@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev) static void ieee80211_master_set_multicast_list(struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; ieee80211_configure_filter(local); } @@ -787,7 +790,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int result; enum ieee80211_band band; struct net_device *mdev; - struct wireless_dev *mwdev; + struct ieee80211_master_priv *mpriv; /* * generic code guarantees at least one band, @@ -829,16 +832,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (hw->queues < 4) hw->ampdu_queues = 0; - mdev = alloc_netdev_mq(sizeof(struct wireless_dev), + mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), "wmaster%d", ether_setup, ieee80211_num_queues(hw)); if (!mdev) goto fail_mdev_alloc; - mwdev = netdev_priv(mdev); - mdev->ieee80211_ptr = mwdev; - mwdev->wiphy = local->hw.wiphy; - + mpriv = netdev_priv(mdev); + mpriv->local = local; local->mdev = mdev; ieee80211_rx_bss_list_init(local); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 30cf891fd3a..8013277924f 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct ieee80211_local *local = wdev_priv(&sdata->wdev); + struct ieee80211_local *local = sdata->local; queue_work(local->hw.workqueue, &ifmsh->work); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 92d898b901e..3ab9670f180 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) return result; } -static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) +static void ap_sta_ps_start(struct sta_info *sta) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = sta->sdata; DECLARE_MAC_BUF(mac); - sdata = sta->sdata; - atomic_inc(&sdata->bss->num_sta_ps); set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", - dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); + sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } -static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) +static int ap_sta_ps_end(struct sta_info *sta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = sta->sdata; + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; int sent = 0; - struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_info *info; DECLARE_MAC_BUF(mac); - sdata = sta->sdata; - atomic_dec(&sdata->bss->num_sta_ps); clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); @@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", - dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); + sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ @@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) sent++; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " - "since STA not sleeping anymore\n", dev->name, + "since STA not sleeping anymore\n", sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ info->flags |= IEEE80211_TX_CTL_REQUEUE; @@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) { struct sta_info *sta = rx->sta; - struct net_device *dev = rx->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; if (!sta) @@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) * exchange sequence */ if (test_sta_flags(sta, WLAN_STA_PS) && !ieee80211_has_pm(hdr->frame_control)) - rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); + rx->sent_ps_buffered += ap_sta_ps_end(sta); else if (!test_sta_flags(sta, WLAN_STA_PS) && ieee80211_has_pm(hdr->frame_control)) - ap_sta_ps_start(dev, sta); + ap_sta_ps_start(sta); } /* Drop data::nullfunc frames silently, since they are used only to diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b4..00d798cc9e0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, return cpu_to_le16(dur); } -static int inline is_ieee80211_device(struct net_device *dev, - struct net_device *master) +static int inline is_ieee80211_device(struct ieee80211_local *local, + struct net_device *dev) { - return (wdev_priv(dev->ieee80211_ptr) == - wdev_priv(master->ieee80211_ptr)); + return local == wdev_priv(dev->ieee80211_ptr); } /* tx handlers */ @@ -1001,14 +1000,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, /* * NB: @tx is uninitialised when passed in here */ -static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, - struct sk_buff *skb, - struct net_device *mdev) +static int ieee80211_tx_prepare(struct ieee80211_local *local, + struct ieee80211_tx_data *tx, + struct sk_buff *skb) { struct net_device *dev; dev = dev_get_by_index(&init_net, skb->iif); - if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { + if (unlikely(dev && !is_ieee80211_device(local, dev))) { dev_put(dev); dev = NULL; } @@ -1258,6 +1257,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) { + struct ieee80211_master_priv *mpriv = netdev_priv(dev); + struct ieee80211_local *local = mpriv->local; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct net_device *odev = NULL; @@ -1273,7 +1274,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, if (skb->iif) odev = dev_get_by_index(&init_net, skb->iif); - if (unlikely(odev && !is_ieee80211_device(odev, dev))) { + if (unlikely(odev && !is_ieee80211_device(local, odev))) { dev_put(odev); odev = NULL; } @@ -1449,8 +1450,8 @@ fail: int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int ret = 1, head_need; u16 ethertype, hdrlen, meshhdrlen = 0; __le16 fc; @@ -1462,7 +1463,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct sta_info *sta; u32 sta_flags = 0; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (unlikely(skb->len < ETH_HLEN)) { ret = 0; goto fail; @@ -2032,7 +2032,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, cpu_to_le16(IEEE80211_FCTL_MOREDATA); } - if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) + if (!ieee80211_tx_prepare(local, &tx, skb)) break; dev_kfree_skb_any(skb); } -- cgit v1.2.3-70-g09d2