]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac802...
authorJohn W. Linville <linville@tuxdriver.com>
Thu, 12 Jul 2012 19:21:05 +0000 (15:21 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 12 Jul 2012 19:21:05 +0000 (15:21 -0400)
Conflicts:
drivers/net/wireless/iwmc3200wifi/cfg80211.c
drivers/net/wireless/mwifiex/cfg80211.c

44 files changed:
Documentation/DocBook/80211.tmpl
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/core.c
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/orinoco/cfg.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/rt2x00config.c
include/linux/nl80211.h
include/net/cfg80211.h
include/net/mac80211.h
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/status.c
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/scan.c
net/wireless/sme.c
net/wireless/util.c

index f3e214f9e25675660257eb25060bd62890b049b7..42e7f030cb161f018992ffd72fc64508201c9ddf 100644 (file)
 !Finclude/net/mac80211.h ieee80211_get_tkip_p1k
 !Finclude/net/mac80211.h ieee80211_get_tkip_p1k_iv
 !Finclude/net/mac80211.h ieee80211_get_tkip_p2k
-!Finclude/net/mac80211.h ieee80211_key_removed
       </chapter>
 
       <chapter id="powersave">
index aca1d2689e907fce2d5a9841e5acfad515c3ee50..86aeef4b9d7ee9295fe04c5533d3959a19474c9c 100644 (file)
@@ -966,11 +966,11 @@ static int ath6kl_set_probed_ssids(struct ath6kl *ar,
        return 0;
 }
 
-static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
                                struct cfg80211_scan_request *request)
 {
-       struct ath6kl *ar = ath6kl_priv(ndev);
-       struct ath6kl_vif *vif = netdev_priv(ndev);
+       struct ath6kl_vif *vif = ath6kl_vif_from_wdev(request->wdev);
+       struct ath6kl *ar = ath6kl_priv(vif->ndev);
        s8 n_channels = 0;
        u16 *channels = NULL;
        int ret = 0;
@@ -1487,14 +1487,14 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
        return 0;
 }
 
-static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
-                                                   char *name,
-                                                   enum nl80211_iftype type,
-                                                   u32 *flags,
-                                                   struct vif_params *params)
+static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
+                                                     char *name,
+                                                     enum nl80211_iftype type,
+                                                     u32 *flags,
+                                                     struct vif_params *params)
 {
        struct ath6kl *ar = wiphy_priv(wiphy);
-       struct net_device *ndev;
+       struct wireless_dev *wdev;
        u8 if_idx, nw_type;
 
        if (ar->num_vif == ar->vif_max) {
@@ -1507,20 +1507,20 @@ static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
                return ERR_PTR(-EINVAL);
        }
 
-       ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
-       if (!ndev)
+       wdev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
+       if (!wdev)
                return ERR_PTR(-ENOMEM);
 
        ar->num_vif++;
 
-       return ndev;
+       return wdev;
 }
 
 static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
-                                    struct net_device *ndev)
+                                    struct wireless_dev *wdev)
 {
        struct ath6kl *ar = wiphy_priv(wiphy);
-       struct ath6kl_vif *vif = netdev_priv(ndev);
+       struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
 
        spin_lock_bh(&ar->list_lock);
        list_del(&vif->list);
@@ -2975,14 +2975,14 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int ath6kl_remain_on_channel(struct wiphy *wiphy,
-                                   struct net_device *dev,
+                                   struct wireless_dev *wdev,
                                    struct ieee80211_channel *chan,
                                    enum nl80211_channel_type channel_type,
                                    unsigned int duration,
                                    u64 *cookie)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
-       struct ath6kl_vif *vif = netdev_priv(dev);
+       struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
+       struct ath6kl *ar = ath6kl_priv(vif->ndev);
        u32 id;
 
        /* TODO: if already pending or ongoing remain-on-channel,
@@ -2999,11 +2999,11 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
 }
 
 static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
-                                          struct net_device *dev,
+                                          struct wireless_dev *wdev,
                                           u64 cookie)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
-       struct ath6kl_vif *vif = netdev_priv(dev);
+       struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
+       struct ath6kl *ar = ath6kl_priv(vif->ndev);
 
        if (cookie != vif->last_roc_id)
                return -ENOENT;
@@ -3134,15 +3134,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
        return false;
 }
 
-static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                          struct ieee80211_channel *chan, bool offchan,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
                          bool dont_wait_for_ack, u64 *cookie)
 {
-       struct ath6kl *ar = ath6kl_priv(dev);
-       struct ath6kl_vif *vif = netdev_priv(dev);
+       struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
+       struct ath6kl *ar = ath6kl_priv(vif->ndev);
        u32 id;
        const struct ieee80211_mgmt *mgmt;
        bool more_data, queued;
@@ -3187,10 +3187,10 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
-                                      struct net_device *dev,
+                                      struct wireless_dev *wdev,
                                       u16 frame_type, bool reg)
 {
-       struct ath6kl_vif *vif = netdev_priv(dev);
+       struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
 
        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
                   __func__, frame_type, reg);
@@ -3477,9 +3477,9 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
        ar->num_vif--;
 }
 
-struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
-                                       enum nl80211_iftype type, u8 fw_vif_idx,
-                                       u8 nw_type)
+struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name,
+                                         enum nl80211_iftype type,
+                                         u8 fw_vif_idx, u8 nw_type)
 {
        struct net_device *ndev;
        struct ath6kl_vif *vif;
@@ -3533,7 +3533,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
        list_add_tail(&vif->list, &ar->vif_list);
        spin_unlock_bh(&ar->list_lock);
 
-       return ndev;
+       return &vif->wdev;
 
 err:
        aggr_module_destroy(vif->aggr_cntxt);
index b992046a1b0e83f4f37fc149dea2bbcee82b2f7d..56b1ebe79812d0d90b2fc6292592809fae9637c1 100644 (file)
@@ -25,9 +25,9 @@ enum ath6kl_cfg_suspend_mode {
        ATH6KL_CFG_SUSPEND_SCHED_SCAN,
 };
 
-struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
-                                       enum nl80211_iftype type,
-                                       u8 fw_vif_idx, u8 nw_type);
+struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name,
+                                         enum nl80211_iftype type,
+                                         u8 fw_vif_idx, u8 nw_type);
 void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
                                      enum wmi_phy_mode mode);
 void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
index fdb3b1decc76716c4c4f41004bb4f7a7bf3bfcc1..82c4dd2a960e5077f7a9f11e1201cabf3b75be04 100644 (file)
@@ -56,7 +56,7 @@ EXPORT_SYMBOL(ath6kl_core_rx_complete);
 int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
 {
        struct ath6kl_bmi_target_info targ_info;
-       struct net_device *ndev;
+       struct wireless_dev *wdev;
        int ret = 0, i;
 
        switch (htc_type) {
@@ -187,12 +187,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
        rtnl_lock();
 
        /* Add an initial station interface */
-       ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
+       wdev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
                                    INFRA_NETWORK);
 
        rtnl_unlock();
 
-       if (!ndev) {
+       if (!wdev) {
                ath6kl_err("Failed to instantiate a network device\n");
                ret = -ENOMEM;
                wiphy_unregister(ar->wiphy);
@@ -200,7 +200,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
        }
 
        ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
-                  __func__, ndev->name, ndev, ar);
+                  __func__, wdev->netdev->name, wdev->netdev, ar);
 
        return ret;
 
index d38a31de344ca4eaecde32642fc8c8bf0f41c2d3..cec49a31029aa9711682d1ede1f862c58aa8ed30 100644 (file)
@@ -589,6 +589,11 @@ struct ath6kl_vif {
        struct list_head mc_filter;
 };
 
+static inline struct ath6kl_vif *ath6kl_vif_from_wdev(struct wireless_dev *wdev)
+{
+       return container_of(wdev, struct ath6kl_vif, wdev);
+}
+
 #define WOW_LIST_ID            0
 #define WOW_HOST_REQ_DELAY     500 /* ms */
 
index a6caa673e8ad944fc41bb2c3b45e48c47bcfbd7f..c30ab4b11d614c8188afc53d61ad3dee8b29a9ba 100644 (file)
@@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
                return -EINVAL;
        }
        id = vif->last_roc_id;
-       cfg80211_ready_on_channel(vif->ndev, id, chan, NL80211_CHAN_NO_HT,
+       cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT,
                                  dur, GFP_ATOMIC);
 
        return 0;
@@ -513,7 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
        else
                id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
        vif->last_cancel_roc_id = 0;
-       cfg80211_remain_on_channel_expired(vif->ndev, id, chan,
+       cfg80211_remain_on_channel_expired(&vif->wdev, id, chan,
                                           NL80211_CHAN_NO_HT, GFP_ATOMIC);
 
        return 0;
@@ -533,7 +533,7 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len,
        ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
                   id, ev->ack_status);
        if (wmi->last_mgmt_tx_frame) {
-               cfg80211_mgmt_tx_status(vif->ndev, id,
+               cfg80211_mgmt_tx_status(&vif->wdev, id,
                                        wmi->last_mgmt_tx_frame,
                                        wmi->last_mgmt_tx_frame_len,
                                        !!ev->ack_status, GFP_ATOMIC);
@@ -568,7 +568,7 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
                   dlen, freq, vif->probe_req_report);
 
        if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
-               cfg80211_rx_mgmt(vif->ndev, freq, 0,
+               cfg80211_rx_mgmt(&vif->wdev, freq, 0,
                                 ev->data, dlen, GFP_ATOMIC);
 
        return 0;
@@ -608,7 +608,7 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
                return -EINVAL;
        }
        ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
-       cfg80211_rx_mgmt(vif->ndev, freq, 0,
+       cfg80211_rx_mgmt(&vif->wdev, freq, 0,
                         ev->data, dlen, GFP_ATOMIC);
 
        return 0;
index d13ae9c299f21db0f09182e3a509876c47938162..c6a10caec79fb94f6d0b9630f29424ea66445828 100644 (file)
@@ -691,9 +691,10 @@ scan_out:
 }
 
 static s32
-brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+brcmf_cfg80211_scan(struct wiphy *wiphy,
                 struct cfg80211_scan_request *request)
 {
+       struct net_device *ndev = request->wdev->netdev;
        s32 err = 0;
 
        WL_TRACE("Enter\n");
index 0f8a7703eea3c493486bc09b049a77f6a89a7a9b..0370403fd0bd5d2345704f8fc766c5ad2260a7dc 100644 (file)
@@ -5359,7 +5359,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (changes & BSS_CHANGED_ASSOC) {
                D_MAC80211("ASSOC %d\n", bss_conf->assoc);
                if (bss_conf->assoc) {
-                       il->timestamp = bss_conf->last_tsf;
+                       il->timestamp = bss_conf->sync_tsf;
 
                        if (!il_is_rfkill(il))
                                il->ops->post_associate(il);
index 6ee940f497f9756c2acf1375df9b02a937b52e24..10896393e5a05be9b44de522f388eb91603b81a8 100644 (file)
@@ -1447,7 +1447,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 
        if (changes & BSS_CHANGED_ASSOC) {
                if (bss_conf->assoc) {
-                       priv->timestamp = bss_conf->last_tsf;
+                       priv->timestamp = bss_conf->sync_tsf;
                        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
                } else {
                        /*
index f4a203049fb470d59d5beb2064208ab82d5734e4..706781316195a9b897f73313ffbe4b44ebefb50f 100644 (file)
@@ -805,7 +805,6 @@ void lbs_scan_done(struct lbs_private *priv)
 }
 
 static int lbs_cfg_scan(struct wiphy *wiphy,
-       struct net_device *dev,
        struct cfg80211_scan_request *request)
 {
        struct lbs_private *priv = wiphy_priv(wiphy);
index 6c57e832ae8396032fdc2f452a70867d223cf0b8..e27b3168862cdf72075b3125c3f93175692ecd25 100644 (file)
@@ -1440,9 +1440,10 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
  * it also informs the results.
  */
 static int
-mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
+mwifiex_cfg80211_scan(struct wiphy *wiphy,
                      struct cfg80211_scan_request *request)
 {
+       struct net_device *dev = request->wdev->netdev;
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        int i;
        struct ieee80211_channel *chan;
@@ -1576,11 +1577,11 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
 /*
  *  create a new virtual interface with the given name
  */
-struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
-                                           char *name,
-                                           enum nl80211_iftype type,
-                                           u32 *flags,
-                                           struct vif_params *params)
+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+                                             char *name,
+                                             enum nl80211_iftype type,
+                                             u32 *flags,
+                                             struct vif_params *params)
 {
        struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
        struct mwifiex_private *priv;
@@ -1701,16 +1702,16 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
 #ifdef CONFIG_DEBUG_FS
        mwifiex_dev_debugfs_init(priv);
 #endif
-       return dev;
+       return wdev;
 }
 EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
 
 /*
  * del_virtual_intf: remove the virtual interface determined by dev
  */
-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
-       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
 
 #ifdef CONFIG_DEBUG_FS
        mwifiex_dev_debugfs_remove(priv);
@@ -1722,11 +1723,11 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
        if (netif_carrier_ok(priv->netdev))
                netif_carrier_off(priv->netdev);
 
-       if (dev->reg_state == NETREG_REGISTERED)
-               unregister_netdevice(dev);
+       if (wdev->netdev->reg_state == NETREG_REGISTERED)
+               unregister_netdevice(wdev->netdev);
 
-       if (dev->reg_state == NETREG_UNREGISTERED)
-               free_netdev(dev);
+       if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
+               free_netdev(wdev->netdev);
 
        /* Clear the priv in adapter */
        priv->netdev = NULL;
index f0219efc895386bf8f507ec8a64e94809d17c743..46803621d01511dad87b91b59ef2b6fb8a38a9ef 100644 (file)
@@ -377,7 +377,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
        goto done;
 
 err_add_intf:
-       mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
+       mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
        rtnl_unlock();
 err_init_fw:
        pr_debug("info: %s: unregister device\n", __func__);
@@ -844,7 +844,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
 
                rtnl_lock();
                if (priv->wdev && priv->netdev)
-                       mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
+                       mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
                rtnl_unlock();
        }
 
index 9e636535cbf6a927a04fc548c132e52b6366ae67..774880d5cb5687194f09ca96a39b0d9b62b104e7 100644 (file)
@@ -1005,10 +1005,12 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
 int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
                                        struct mwifiex_bssdescriptor *bss_desc);
 
-struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
-                                       char *name, enum nl80211_iftype type,
-                                       u32 *flags, struct vif_params *params);
-int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
+struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
+                                             char *name,
+                                             enum nl80211_iftype type,
+                                             u32 *flags,
+                                             struct vif_params *params);
+int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
 
 void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
 
index e15675585fb10ae21a16ba7c9210fb3f703911c2..7b751fba7e1f90176d797ab1a2bc88ce72e5f6ac 100644 (file)
@@ -138,7 +138,7 @@ static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
        return err;
 }
 
-static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
+static int orinoco_scan(struct wiphy *wiphy,
                        struct cfg80211_scan_request *request)
 {
        struct orinoco_private *priv = wiphy_priv(wiphy);
index dfcd02ab6cae5add70a2eb47c703d54b32c324ce..241162e8111d2584f0fca6f47819cf924cdf1157 100644 (file)
@@ -484,7 +484,7 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy,
                                        enum nl80211_iftype type, u32 *flags,
                                        struct vif_params *params);
 
-static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
+static int rndis_scan(struct wiphy *wiphy,
                        struct cfg80211_scan_request *request);
 
 static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
@@ -1941,9 +1941,10 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
 }
 
 #define SCAN_DELAY_JIFFIES (6 * HZ)
-static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
+static int rndis_scan(struct wiphy *wiphy,
                        struct cfg80211_scan_request *request)
 {
+       struct net_device *dev = request->wdev->netdev;
        struct usbnet *usbdev = netdev_priv(dev);
        struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
        int ret;
index e7361d913e8e2a8008f240ffdfb3269a0ee4c753..49a63e973934b30a87117babb8305fe5c8609631 100644 (file)
@@ -102,7 +102,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
 
        /* Update the AID, this is needed for dynamic PS support */
        rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
-       rt2x00dev->last_beacon = bss_conf->last_tsf;
+       rt2x00dev->last_beacon = bss_conf->sync_tsf;
 
        /* Update global beacon interval time, this is needed for PS support */
        rt2x00dev->beacon_int = bss_conf->beacon_int;
index db961a59247f0b175a5c16a4000029d62a6bca7d..e791487ead37e581d9f93b475c24a40909d9dd08 100644 (file)
@@ -771,6 +771,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_IFNAME: network interface name
  * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
  *
+ * @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices
+ *     that don't have a netdev (u64)
+ *
  * @NL80211_ATTR_MAC: MAC address (various uses)
  *
  * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
@@ -1493,6 +1496,8 @@ enum nl80211_attrs {
 
        NL80211_ATTR_BG_SCAN_PERIOD,
 
+       NL80211_ATTR_WDEV,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
index 51f67a9003a92b70b44337e1ffca08010af2dd75..5a67165f3b190e61b682a4868b73295dee720bcb 100644 (file)
@@ -999,7 +999,7 @@ struct cfg80211_ssid {
  * @ie_len: length of ie in octets
  * @rates: bitmap of rates to advertise for each band
  * @wiphy: the wiphy this was for
- * @dev: the interface
+ * @wdev: the wireless device to scan for
  * @aborted: (internal) scan request was notified as aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
  */
@@ -1012,9 +1012,10 @@ struct cfg80211_scan_request {
 
        u32 rates[IEEE80211_NUM_BANDS];
 
+       struct wireless_dev *wdev;
+
        /* internal */
        struct wiphy *wiphy;
-       struct net_device *dev;
        bool aborted;
        bool no_cck;
 
@@ -1435,10 +1436,10 @@ struct cfg80211_gtk_rekey_data {
  *
  * @add_virtual_intf: create a new virtual interface with the given name,
  *     must set the struct wireless_dev's iftype. Beware: You must create
- *     the new netdev in the wiphy's network namespace! Returns the netdev,
- *     or an ERR_PTR.
+ *     the new netdev in the wiphy's network namespace! Returns the struct
+ *     wireless_dev, or an ERR_PTR.
  *
- * @del_virtual_intf: remove the virtual interface determined by ifindex.
+ * @del_virtual_intf: remove the virtual interface
  *
  * @change_virtual_intf: change type/configuration of virtual interface,
  *     keep the struct wireless_dev's iftype updated.
@@ -1617,12 +1618,13 @@ struct cfg80211_ops {
        int     (*resume)(struct wiphy *wiphy);
        void    (*set_wakeup)(struct wiphy *wiphy, bool enabled);
 
-       struct net_device * (*add_virtual_intf)(struct wiphy *wiphy,
-                                               char *name,
-                                               enum nl80211_iftype type,
-                                               u32 *flags,
-                                               struct vif_params *params);
-       int     (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev);
+       struct wireless_dev * (*add_virtual_intf)(struct wiphy *wiphy,
+                                                 char *name,
+                                                 enum nl80211_iftype type,
+                                                 u32 *flags,
+                                                 struct vif_params *params);
+       int     (*del_virtual_intf)(struct wiphy *wiphy,
+                                   struct wireless_dev *wdev);
        int     (*change_virtual_intf)(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       enum nl80211_iftype type, u32 *flags,
@@ -1699,7 +1701,7 @@ struct cfg80211_ops {
                                       struct ieee80211_channel *chan,
                                       enum nl80211_channel_type channel_type);
 
-       int     (*scan)(struct wiphy *wiphy, struct net_device *dev,
+       int     (*scan)(struct wiphy *wiphy,
                        struct cfg80211_scan_request *request);
 
        int     (*auth)(struct wiphy *wiphy, struct net_device *dev,
@@ -1753,23 +1755,23 @@ struct cfg80211_ops {
        int     (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
 
        int     (*remain_on_channel)(struct wiphy *wiphy,
-                                    struct net_device *dev,
+                                    struct wireless_dev *wdev,
                                     struct ieee80211_channel *chan,
                                     enum nl80211_channel_type channel_type,
                                     unsigned int duration,
                                     u64 *cookie);
        int     (*cancel_remain_on_channel)(struct wiphy *wiphy,
-                                           struct net_device *dev,
+                                           struct wireless_dev *wdev,
                                            u64 cookie);
 
-       int     (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev,
+       int     (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
                          struct ieee80211_channel *chan, bool offchan,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
                          bool dont_wait_for_ack, u64 *cookie);
        int     (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
-                                      struct net_device *dev,
+                                      struct wireless_dev *wdev,
                                       u64 cookie);
 
        int     (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
@@ -1780,7 +1782,7 @@ struct cfg80211_ops {
                                       s32 rssi_thold, u32 rssi_hyst);
 
        void    (*mgmt_frame_register)(struct wiphy *wiphy,
-                                      struct net_device *dev,
+                                      struct wireless_dev *wdev,
                                       u16 frame_type, bool reg);
 
        int     (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
@@ -2341,17 +2343,25 @@ struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
 
 /**
- * struct wireless_dev - wireless per-netdev state
+ * struct wireless_dev - wireless device state
+ *
+ * For netdevs, this structure must be allocated by the driver
+ * that uses the ieee80211_ptr field in struct net_device (this
+ * is intentional so it can be allocated along with the netdev.)
+ * It need not be registered then as netdev registration will
+ * be intercepted by cfg80211 to see the new wireless device.
  *
- * This structure must be allocated by the driver/stack
- * that uses the ieee80211_ptr field in struct net_device
- * (this is intentional so it can be allocated along with
- * the netdev.)
+ * For non-netdev uses, it must also be allocated by the driver
+ * in response to the cfg80211 callbacks that require it, as
+ * there's no netdev registration in that case it may not be
+ * allocated outside of callback operations that return it.
  *
  * @wiphy: pointer to hardware description
  * @iftype: interface type
  * @list: (private) Used to collect the interfaces
- * @netdev: (private) Used to reference back to the netdev
+ * @netdev: (private) Used to reference back to the netdev, may be %NULL
+ * @identifier: (private) Identifier used in nl80211 to identify this
+ *     wireless device if it has no netdev
  * @current_bss: (private) Used by the internal configuration code
  * @channel: (private) Used by the internal configuration code to track
  *     the user-set AP, monitor and WDS channel
@@ -2383,6 +2393,8 @@ struct wireless_dev {
        struct list_head list;
        struct net_device *netdev;
 
+       u32 identifier;
+
        struct list_head mgmt_registrations;
        spinlock_t mgmt_registrations_lock;
 
@@ -3269,7 +3281,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
 
 /**
  * cfg80211_ready_on_channel - notification of remain_on_channel start
- * @dev: network device
+ * @wdev: wireless device
  * @cookie: the request cookie
  * @chan: The current channel (from remain_on_channel request)
  * @channel_type: Channel type
@@ -3277,21 +3289,20 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
  *     channel
  * @gfp: allocation flags
  */
-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
+void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
                               struct ieee80211_channel *chan,
                               enum nl80211_channel_type channel_type,
                               unsigned int duration, gfp_t gfp);
 
 /**
  * cfg80211_remain_on_channel_expired - remain_on_channel duration expired
- * @dev: network device
+ * @wdev: wireless device
  * @cookie: the request cookie
  * @chan: The current channel (from remain_on_channel request)
  * @channel_type: Channel type
  * @gfp: allocation flags
  */
-void cfg80211_remain_on_channel_expired(struct net_device *dev,
-                                       u64 cookie,
+void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
                                        struct ieee80211_channel *chan,
                                        enum nl80211_channel_type channel_type,
                                        gfp_t gfp);
@@ -3319,7 +3330,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
 
 /**
  * cfg80211_rx_mgmt - notification of received, unprocessed management frame
- * @dev: network device
+ * @wdev: wireless device receiving the frame
  * @freq: Frequency on which the frame was received in MHz
  * @sig_dbm: signal strength in mBm, or 0 if unknown
  * @buf: Management frame (header + body)
@@ -3334,12 +3345,12 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
  * This function is called whenever an Action frame is received for a station
  * mode interface, but is not processed in kernel.
  */
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
+bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm,
                      const u8 *buf, size_t len, gfp_t gfp);
 
 /**
  * cfg80211_mgmt_tx_status - notification of TX status for management frame
- * @dev: network device
+ * @wdev: wireless device receiving the frame
  * @cookie: Cookie returned by cfg80211_ops::mgmt_tx()
  * @buf: Management frame (header + body)
  * @len: length of the frame data
@@ -3350,7 +3361,7 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm,
  * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the
  * transmission attempt.
  */
-void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
                             const u8 *buf, size_t len, bool ack, gfp_t gfp);
 
 
index e3fa90ce9ecb0691879c21a3beca687a9702fcbb..bb86aa6f98dd065d701d37d6ba4a18b2d55f00ae 100644 (file)
@@ -233,8 +233,10 @@ enum ieee80211_rssi_event {
  *     valid in station mode only while @assoc is true and if also
  *     requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf
  *     @ps_dtim_period)
- * @last_tsf: last beacon's/probe response's TSF timestamp (could be old
+ * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old
  *     as it may have been received during scanning long ago)
+ * @sync_device_ts: the device timestamp corresponding to the sync_tsf,
+ *     the driver/device can use this to calculate synchronisation
  * @beacon_int: beacon interval
  * @assoc_capability: capabilities taken from assoc resp
  * @basic_rates: bitmap of basic rates, each bit stands for an
@@ -281,7 +283,8 @@ struct ieee80211_bss_conf {
        u8 dtim_period;
        u16 beacon_int;
        u16 assoc_capability;
-       u64 last_tsf;
+       u64 sync_tsf;
+       u32 sync_device_ts;
        u32 basic_rates;
        int mcast_rate[IEEE80211_NUM_BANDS];
        u16 ht_operation_mode;
@@ -696,6 +699,8 @@ enum mac80211_rx_flags {
  *
  * @mactime: value in microseconds of the 64-bit Time Synchronization Function
  *     (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
+ * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use
+ *     it but can store it and pass it back to the driver for synchronisation
  * @band: the active band when this frame was received
  * @freq: frequency the radio was tuned to when receiving this frame, in MHz
  * @signal: signal strength when receiving this frame, either in dBm, in dB or
@@ -709,13 +714,14 @@ enum mac80211_rx_flags {
  */
 struct ieee80211_rx_status {
        u64 mactime;
-       enum ieee80211_band band;
-       int freq;
-       int signal;
-       int antenna;
-       int rate_idx;
-       int flag;
-       unsigned int rx_flags;
+       u32 device_timestamp;
+       u16 flag;
+       u16 freq;
+       u8 rate_idx;
+       u8 rx_flags;
+       u8 band;
+       u8 antenna;
+       s8 signal;
 };
 
 /**
@@ -3591,22 +3597,6 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
 void ieee80211_request_smps(struct ieee80211_vif *vif,
                            enum ieee80211_smps_mode smps_mode);
 
-/**
- * ieee80211_key_removed - disable hw acceleration for key
- * @key_conf: The key hw acceleration should be disabled for
- *
- * This allows drivers to indicate that the given key has been
- * removed from hardware acceleration, due to a new key that
- * was added. Don't use this if the key can continue to be used
- * for TX, if the key restriction is on RX only it is permitted
- * to keep the key for TX only and not call this function.
- *
- * Due to locking constraints, it may only be called during
- * @set_key. This function must be allowed to sleep, and the
- * key it tries to disable may still be used until it returns.
- */
-void ieee80211_key_removed(struct ieee80211_key_conf *key_conf);
-
 /**
  * ieee80211_ready_on_channel - notification of remain-on-channel start
  * @hw: pointer as obtained from ieee80211_alloc_hw()
index 5cc1bf7d803336619a39f7e2e7370829db6aa230..d0deb3edae21fe4a1fc3cbbc7773e742945197f4 100644 (file)
@@ -135,7 +135,8 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
        bar->control = cpu_to_le16(bar_control);
        bar->start_seq_num = cpu_to_le16(ssn);
 
-       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+                                       IEEE80211_TX_CTL_REQ_TX_STATUS;
        ieee80211_tx_skb_tid(sdata, skb, tid);
 }
 EXPORT_SYMBOL(ieee80211_send_bar);
index ccbe2413142aba954200793a278f68d7e2abfd22..cfdc03f59e27200443d02c5a650335d1fb038896 100644 (file)
 #include "rate.h"
 #include "mesh.h"
 
-static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name,
-                                             enum nl80211_iftype type,
-                                             u32 *flags,
-                                             struct vif_params *params)
+static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, char *name,
+                                               enum nl80211_iftype type,
+                                               u32 *flags,
+                                               struct vif_params *params)
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       struct net_device *dev;
+       struct wireless_dev *wdev;
        struct ieee80211_sub_if_data *sdata;
        int err;
 
-       err = ieee80211_if_add(local, name, &dev, type, params);
+       err = ieee80211_if_add(local, name, &wdev, type, params);
        if (err)
                return ERR_PTR(err);
 
        if (type == NL80211_IFTYPE_MONITOR && flags) {
-               sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+               sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
                sdata->u.mntr_flags = *flags;
        }
 
-       return dev;
+       return wdev;
 }
 
-static int ieee80211_del_iface(struct wiphy *wiphy, struct net_device *dev)
+static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
-       ieee80211_if_remove(IEEE80211_DEV_TO_SUB_IF(dev));
+       ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));
 
        return 0;
 }
@@ -1741,6 +1741,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
                return -EINVAL;
        }
 
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+
        return 0;
 }
 
@@ -1761,10 +1763,11 @@ static int ieee80211_resume(struct wiphy *wiphy)
 #endif
 
 static int ieee80211_scan(struct wiphy *wiphy,
-                         struct net_device *dev,
                          struct cfg80211_scan_request *req)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_WDEV_TO_SUB_IF(req->wdev);
 
        switch (ieee80211_vif_type_p2p(&sdata->vif)) {
        case NL80211_IFTYPE_STATION:
@@ -2297,13 +2300,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
 }
 
 static int ieee80211_remain_on_channel(struct wiphy *wiphy,
-                                      struct net_device *dev,
+                                      struct wireless_dev *wdev,
                                       struct ieee80211_channel *chan,
                                       enum nl80211_channel_type channel_type,
                                       unsigned int duration,
                                       u64 *cookie)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        struct ieee80211_local *local = sdata->local;
        int ret;
 
@@ -2390,23 +2393,23 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 }
 
 static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
-                                             struct net_device *dev,
+                                             struct wireless_dev *wdev,
                                              u64 cookie)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        struct ieee80211_local *local = sdata->local;
 
        return ieee80211_cancel_roc(local, cookie, false);
 }
 
-static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
+static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                             struct ieee80211_channel *chan, bool offchan,
                             enum nl80211_channel_type channel_type,
                             bool channel_type_valid, unsigned int wait,
                             const u8 *buf, size_t len, bool no_cck,
                             bool dont_wait_for_ack, u64 *cookie)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        struct sta_info *sta;
@@ -2511,21 +2514,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
-                                        struct net_device *dev,
+                                        struct wireless_dev *wdev,
                                         u64 cookie)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_local *local = wiphy_priv(wiphy);
 
        return ieee80211_cancel_roc(local, cookie, true);
 }
 
 static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
-                                         struct net_device *dev,
+                                         struct wireless_dev *wdev,
                                          u16 frame_type, bool reg)
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
        switch (frame_type) {
        case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH:
index 778e5916d7c3e140ccc3cb98012b39204e3003c7..b8dfb440c8ef1ff903e3359e35b041ea9093d358 100644 (file)
@@ -325,8 +325,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
                local->rx_handlers_drop_defrag);
        DEBUGFS_STATS_ADD(rx_handlers_drop_short,
                local->rx_handlers_drop_short);
-       DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan,
-               local->rx_handlers_drop_passive_scan);
        DEBUGFS_STATS_ADD(tx_expand_skb_head,
                local->tx_expand_skb_head);
        DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned,
index e0423f8c0ce1a84e87f52ab67c58915f580f1bec..7998513ec83144536af139f7d9c36d0392cec8d3 100644 (file)
@@ -85,6 +85,8 @@ struct ieee80211_bss {
        size_t ssid_len;
        u8 ssid[IEEE80211_MAX_SSID_LEN];
 
+       u32 device_ts;
+
        u8 dtim_period;
 
        bool wmm_used;
@@ -207,7 +209,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
  * enum ieee80211_packet_rx_flags - packet RX flags
  * @IEEE80211_RX_RA_MATCH: frame is destined to interface currently processed
  *     (incl. multicast frames)
- * @IEEE80211_RX_IN_SCAN: received while scanning
  * @IEEE80211_RX_FRAGMENTED: fragmented frame
  * @IEEE80211_RX_AMSDU: a-MSDU packet
  * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed
@@ -217,7 +218,6 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
  * @rx_flags field of &struct ieee80211_rx_status.
  */
 enum ieee80211_packet_rx_flags {
-       IEEE80211_RX_IN_SCAN                    = BIT(0),
        IEEE80211_RX_RA_MATCH                   = BIT(1),
        IEEE80211_RX_FRAGMENTED                 = BIT(2),
        IEEE80211_RX_AMSDU                      = BIT(3),
@@ -965,14 +965,14 @@ struct ieee80211_local {
        int scan_channel_idx;
        int scan_ies_len;
 
-       bool sched_scanning;
        struct ieee80211_sched_scan_ies sched_scan_ies;
        struct work_struct sched_scan_stopped_work;
+       struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
 
        unsigned long leave_oper_channel_time;
        enum mac80211_scan_state next_scan_state;
        struct delayed_work scan_work;
-       struct ieee80211_sub_if_data *scan_sdata;
+       struct ieee80211_sub_if_data __rcu *scan_sdata;
        enum nl80211_channel_type _oper_channel_type;
        struct ieee80211_channel *oper_channel, *csa_channel;
 
@@ -1014,7 +1014,6 @@ struct ieee80211_local {
        unsigned int rx_handlers_drop_nullfunc;
        unsigned int rx_handlers_drop_defrag;
        unsigned int rx_handlers_drop_short;
-       unsigned int rx_handlers_drop_passive_scan;
        unsigned int tx_expand_skb_head;
        unsigned int tx_expand_skb_head_cloned;
        unsigned int rx_expand_skb_head;
@@ -1091,6 +1090,12 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
        return netdev_priv(dev);
 }
 
+static inline struct ieee80211_sub_if_data *
+IEEE80211_WDEV_TO_SUB_IF(struct wireless_dev *wdev)
+{
+       return container_of(wdev, struct ieee80211_sub_if_data, wdev);
+}
+
 /* this struct represents 802.11n's RA/TID combination */
 struct ieee80211_ra_tid {
        u8 ra[ETH_ALEN];
@@ -1241,8 +1246,7 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
                           struct cfg80211_scan_request *req);
 void ieee80211_scan_cancel(struct ieee80211_local *local);
 void ieee80211_run_deferred_scan(struct ieee80211_local *local);
-ieee80211_rx_result
-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb);
 
 void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
 struct ieee80211_bss *
@@ -1278,7 +1282,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 int ieee80211_iface_init(void);
 void ieee80211_iface_exit(void);
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
-                    struct net_device **new_dev, enum nl80211_iftype type,
+                    struct wireless_dev **new_wdev, enum nl80211_iftype type,
                     struct vif_params *params);
 int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
                             enum nl80211_iftype type);
index fbef7a1ada7aaed349d4cec790643d47c8066b93..334ee0fb18ca0b472933e1effd5f6d13c5101700 100644 (file)
@@ -112,10 +112,11 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
                }
        }
 
-       if (local->scan_sdata &&
-           !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
+       sdata = rcu_dereference_protected(local->scan_sdata,
+                                         lockdep_is_held(&local->mtx));
+       if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) {
                scanning = true;
-               local->scan_sdata->vif.bss_conf.idle = false;
+               sdata->vif.bss_conf.idle = false;
        }
 
        list_for_each_entry(sdata, &local->interfaces, list) {
@@ -333,17 +334,21 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
-       int ret;
+       int ret = 0;
 
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return 0;
 
+       mutex_lock(&local->iflist_mtx);
+
        if (local->monitor_sdata)
-               return 0;
+               goto out_unlock;
 
        sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
-       if (!sdata)
-               return -ENOMEM;
+       if (!sdata) {
+               ret = -ENOMEM;
+               goto out_unlock;
+       }
 
        /* set up data */
        sdata->local = local;
@@ -357,18 +362,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        if (WARN_ON(ret)) {
                /* ok .. stupid driver, it asked for this! */
                kfree(sdata);
-               return ret;
+               goto out_unlock;
        }
 
        ret = ieee80211_check_queues(sdata);
        if (ret) {
                kfree(sdata);
-               return ret;
+               goto out_unlock;
        }
 
        rcu_assign_pointer(local->monitor_sdata, sdata);
-
-       return 0;
+ out_unlock:
+       mutex_unlock(&local->iflist_mtx);
+       return ret;
 }
 
 void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
@@ -378,10 +384,12 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return;
 
-       sdata = rtnl_dereference(local->monitor_sdata);
+       mutex_lock(&local->iflist_mtx);
 
+       sdata = rcu_dereference_protected(local->monitor_sdata,
+                                         lockdep_is_held(&local->iflist_mtx));
        if (!sdata)
-               return;
+               goto out_unlock;
 
        rcu_assign_pointer(local->monitor_sdata, NULL);
        synchronize_net();
@@ -389,6 +397,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        drv_remove_interface(local, sdata);
 
        kfree(sdata);
+ out_unlock:
+       mutex_unlock(&local->iflist_mtx);
 }
 
 /*
@@ -628,7 +638,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
-       if (local->scan_sdata == sdata)
+       if (rcu_access_pointer(local->scan_sdata) == sdata)
                ieee80211_scan_cancel(local);
 
        /*
@@ -1373,7 +1383,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
 }
 
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
-                    struct net_device **new_dev, enum nl80211_iftype type,
+                    struct wireless_dev **new_wdev, enum nl80211_iftype type,
                     struct vif_params *params)
 {
        struct net_device *ndev;
@@ -1463,8 +1473,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
        list_add_tail_rcu(&sdata->list, &local->interfaces);
        mutex_unlock(&local->iflist_mtx);
 
-       if (new_dev)
-               *new_dev = ndev;
+       if (new_wdev)
+               *new_wdev = &sdata->wdev;
 
        return 0;
 
index b3b7e526e245cdb7cb925e9c39146ec6189bd359..7ae678ba5d679dbd40fc7c199c499ed82228757f 100644 (file)
@@ -194,26 +194,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
        key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
 }
 
-void ieee80211_key_removed(struct ieee80211_key_conf *key_conf)
-{
-       struct ieee80211_key *key;
-
-       key = container_of(key_conf, struct ieee80211_key, conf);
-
-       might_sleep();
-       assert_key_lock(key->local);
-
-       key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-
-       /*
-        * Flush TX path to avoid attempts to use this key
-        * after this function returns. Until then, drivers
-        * must be prepared to handle the key.
-        */
-       synchronize_rcu();
-}
-EXPORT_SYMBOL_GPL(ieee80211_key_removed);
-
 static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
                                        int idx, bool uni, bool multi)
 {
index c794101f8987f1227cdd71c656966e1ef6580b44..c26e231c733af85d66fba73821ee877ca4338912 100644 (file)
@@ -322,7 +322,8 @@ static void ieee80211_restart_work(struct work_struct *work)
 
        mutex_lock(&local->mtx);
        WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-            local->sched_scanning,
+            rcu_dereference_protected(local->sched_scan_sdata,
+                                      lockdep_is_held(&local->mtx)),
                "%s called with hardware scan in progress\n", __func__);
        mutex_unlock(&local->mtx);
 
index f49f14f8ba82cddd447872cf84d1cadf2055d25c..de4350fce11e046862de5381d8b0ea090e13a4cf 100644 (file)
@@ -1108,7 +1108,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
 }
 
 /* MLME */
-static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
+static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
                                     struct ieee80211_sub_if_data *sdata,
                                     u8 *wmm_param, size_t wmm_param_len)
 {
@@ -1119,23 +1119,23 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
        u8 *pos, uapsd_queues = 0;
 
        if (!local->ops->conf_tx)
-               return;
+               return false;
 
        if (local->hw.queues < IEEE80211_NUM_ACS)
-               return;
+               return false;
 
        if (!wmm_param)
-               return;
+               return false;
 
        if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
-               return;
+               return false;
 
        if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
                uapsd_queues = ifmgd->uapsd_queues;
 
        count = wmm_param[6] & 0x0f;
        if (count == ifmgd->wmm_last_param_set)
-               return;
+               return false;
        ifmgd->wmm_last_param_set = count;
 
        pos = wmm_param + 8;
@@ -1202,6 +1202,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
 
        /* enable WMM or activate new settings */
        sdata->vif.bss_conf.qos = true;
+       return true;
 }
 
 static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata)
@@ -1268,11 +1269,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 
        bss_info_changed |= BSS_CHANGED_ASSOC;
-       /* set timing information */
-       bss_conf->beacon_int = cbss->beacon_interval;
-       bss_conf->last_tsf = cbss->tsf;
-
-       bss_info_changed |= BSS_CHANGED_BEACON_INT;
        bss_info_changed |= ieee80211_handle_bss_capability(sdata,
                bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
 
@@ -2435,14 +2431,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,
                                                   ifmgd->aid);
 
-       if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) {
-               ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
-                                     true);
-
-               ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
-                                        elems.wmm_param_len);
-       }
-
        if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
                if (directed_tim) {
                        if (local->hw.conf.dynamic_ps_timeout > 0) {
@@ -2473,6 +2461,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        ifmgd->beacon_crc = ncrc;
        ifmgd->beacon_crc_valid = true;
 
+       ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
+                             true);
+
+       if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param,
+                                    elems.wmm_param_len))
+               changed |= BSS_CHANGED_QOS;
+
        if (elems.erp_info && elems.erp_info_len >= 1) {
                erp_valid = true;
                erp_value = elems.erp_info[0];
@@ -2974,7 +2969,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 /* scan finished notification */
 void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
 {
-       struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+       struct ieee80211_sub_if_data *sdata;
 
        /* Restart STA timers */
        rcu_read_lock();
@@ -3132,9 +3127,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 
                memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN);
 
-               /* tell driver about BSSID and basic rates */
+               /* set timing information */
+               sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
+               sdata->vif.bss_conf.sync_tsf = cbss->tsf;
+               sdata->vif.bss_conf.sync_device_ts = bss->device_ts;
+
+               /* tell driver about BSSID, basic rates and timing */
                ieee80211_bss_info_change_notify(sdata,
-                       BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES);
+                       BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
+                       BSS_CHANGED_BEACON_INT);
 
                if (assoc)
                        sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
index b0fb6a2b89ad751cd1a47d594942913582e556f7..8c047fc8b3259456a6d052a635342d286d9601e6 100644 (file)
@@ -191,7 +191,7 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc)
                        roc->frame = NULL;
                }
        } else {
-               cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc,
+               cfg80211_ready_on_channel(&roc->sdata->wdev, (unsigned long)roc,
                                          roc->chan, roc->chan_type,
                                          roc->req_duration, GFP_KERNEL);
        }
@@ -299,7 +299,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
 
        /* was never transmitted */
        if (roc->frame) {
-               cfg80211_mgmt_tx_status(roc->sdata->dev,
+               cfg80211_mgmt_tx_status(&roc->sdata->wdev,
                                        (unsigned long)roc->frame,
                                        roc->frame->data, roc->frame->len,
                                        false, GFP_KERNEL);
@@ -307,7 +307,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
        }
 
        if (!roc->mgmt_tx_cookie)
-               cfg80211_remain_on_channel_expired(roc->sdata->dev,
+               cfg80211_remain_on_channel_expired(&roc->sdata->wdev,
                                                   (unsigned long)roc,
                                                   roc->chan, roc->chan_type,
                                                   GFP_KERNEL);
index f9e51ef8dfa2432ec44168feebc82579f3ac0be6..fb1d4aa65e8c9e68b347e292a583081ac07c50c5 100644 (file)
@@ -626,8 +626,12 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
 
 #ifdef CONFIG_MAC80211_DEBUGFS
        /* use fixed index if set */
-       if (mp->fixed_rate_idx != -1)
-               sample_idx = mp->fixed_rate_idx;
+       if (mp->fixed_rate_idx != -1) {
+               mi->max_tp_rate = mp->fixed_rate_idx;
+               mi->max_tp_rate2 = mp->fixed_rate_idx;
+               mi->max_prob_rate = mp->fixed_rate_idx;
+               sample_idx = -1;
+       }
 #endif
 
        if (sample_idx >= 0) {
index 839cac8fab57425e70623fe85da8107d957c0dac..090d417919af5cfd44413d860feb4e80cf4f6170 100644 (file)
@@ -413,29 +413,6 @@ static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx)
 
 /* rx handlers */
 
-static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
-{
-       struct ieee80211_local *local = rx->local;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-       struct sk_buff *skb = rx->skb;
-
-       if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
-                  !local->sched_scanning))
-               return RX_CONTINUE;
-
-       if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-           test_bit(SCAN_SW_SCANNING, &local->scanning) ||
-           test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
-           local->sched_scanning)
-               return ieee80211_scan_rx(rx->sdata, skb);
-
-       /* scanning finished during invoking of handlers */
-       I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
-       return RX_DROP_UNUSABLE;
-}
-
-
 static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -2404,7 +2381,7 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
        if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
                sig = status->signal;
 
-       if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig,
+       if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
                             rx->skb->data, rx->skb->len,
                             GFP_ATOMIC)) {
                if (rx->sta)
@@ -2695,7 +2672,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
                        goto rxh_next;  \
        } while (0);
 
-       CALL_RXH(ieee80211_rx_h_passive_scan)
        CALL_RXH(ieee80211_rx_h_check)
 
        ieee80211_rx_reorder_ampdu(rx);
@@ -2765,11 +2741,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
                        return 0;
                if (ieee80211_is_beacon(hdr->frame_control)) {
                        return 1;
-               }
-               else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
-                       if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
-                               return 0;
-                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
+               } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
+                       return 0;
                } else if (!multicast &&
                           !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
                        if (!(sdata->dev->flags & IFF_PROMISC))
@@ -2807,11 +2780,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
                         * and location updates. Note that mac80211
                         * itself never looks at these frames.
                         */
-                       if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
-                           ieee80211_is_public_action(hdr, skb->len))
+                       if (ieee80211_is_public_action(hdr, skb->len))
                                return 1;
-                       if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
-                           !ieee80211_is_beacon(hdr->frame_control))
+                       if (!ieee80211_is_beacon(hdr->frame_control))
                                return 0;
                        status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
                }
@@ -2877,7 +2848,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
 static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                         struct sk_buff *skb)
 {
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_hdr *hdr;
@@ -2895,11 +2865,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                local->dot11ReceivedFragmentCount++;
 
-       if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-                    test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning) ||
-                    test_bit(SCAN_SW_SCANNING, &local->scanning)))
-               status->rx_flags |= IEEE80211_RX_IN_SCAN;
-
        if (ieee80211_is_mgmt(fc))
                err = skb_linearize(skb);
        else
@@ -2914,6 +2879,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        ieee80211_parse_qos(&rx);
        ieee80211_verify_alignment(&rx);
 
+       if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) ||
+                    ieee80211_is_beacon(hdr->frame_control)))
+               ieee80211_scan_rx(local, skb);
+
        if (ieee80211_is_data(fc)) {
                prev_sta = NULL;
 
index 379f178eab5f162a7c77f7f1ff66315b901f0f0b..e80a8b644aa04cdf2d4e39933a12a49f3b376072 100644 (file)
@@ -83,13 +83,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 
        cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
                                         mgmt, len, signal, GFP_ATOMIC);
-
        if (!cbss)
                return NULL;
 
        cbss->free_priv = ieee80211_rx_bss_free;
        bss = (void *)cbss->priv;
 
+       bss->device_ts = rx_status->device_timestamp;
+
        if (elems->parse_error) {
                if (beacon)
                        bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
@@ -165,52 +166,47 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
        return bss;
 }
 
-ieee80211_rx_result
-ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
 {
        struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
-       struct ieee80211_mgmt *mgmt;
+       struct ieee80211_sub_if_data *sdata1, *sdata2;
+       struct ieee80211_mgmt *mgmt = (void *)skb->data;
        struct ieee80211_bss *bss;
        u8 *elements;
        struct ieee80211_channel *channel;
        size_t baselen;
        int freq;
-       __le16 fc;
-       bool presp, beacon = false;
+       bool beacon;
        struct ieee802_11_elems elems;
 
-       if (skb->len < 2)
-               return RX_DROP_UNUSABLE;
-
-       mgmt = (struct ieee80211_mgmt *) skb->data;
-       fc = mgmt->frame_control;
+       if (skb->len < 24 ||
+           (!ieee80211_is_probe_resp(mgmt->frame_control) &&
+            !ieee80211_is_beacon(mgmt->frame_control)))
+               return;
 
-       if (ieee80211_is_ctl(fc))
-               return RX_CONTINUE;
+       sdata1 = rcu_dereference(local->scan_sdata);
+       sdata2 = rcu_dereference(local->sched_scan_sdata);
 
-       if (skb->len < 24)
-               return RX_CONTINUE;
+       if (likely(!sdata1 && !sdata2))
+               return;
 
-       presp = ieee80211_is_probe_resp(fc);
-       if (presp) {
+       if (ieee80211_is_probe_resp(mgmt->frame_control)) {
                /* ignore ProbeResp to foreign address */
-               if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
-                       return RX_DROP_MONITOR;
+               if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&
+                   (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
+                       return;
 
-               presp = true;
                elements = mgmt->u.probe_resp.variable;
                baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+               beacon = false;
        } else {
-               beacon = ieee80211_is_beacon(fc);
                baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
                elements = mgmt->u.beacon.variable;
+               beacon = true;
        }
 
-       if (!presp && !beacon)
-               return RX_CONTINUE;
-
        if (baselen > skb->len)
-               return RX_DROP_MONITOR;
+               return;
 
        ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
 
@@ -220,22 +216,16 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
        else
                freq = rx_status->freq;
 
-       channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
+       channel = ieee80211_get_channel(local->hw.wiphy, freq);
 
        if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
-               return RX_DROP_MONITOR;
+               return;
 
-       bss = ieee80211_bss_info_update(sdata->local, rx_status,
+       bss = ieee80211_bss_info_update(local, rx_status,
                                        mgmt, skb->len, &elems,
                                        channel, beacon);
        if (bss)
-               ieee80211_rx_bss_put(sdata->local, bss);
-
-       if (channel == sdata->local->oper_channel)
-               return RX_CONTINUE;
-
-       dev_kfree_skb(skb);
-       return RX_QUEUED;
+               ieee80211_rx_bss_put(local, bss);
 }
 
 /* return false if no more work */
@@ -293,7 +283,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
                return;
 
        if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
-               int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
+               int rc;
+
+               rc = drv_hw_scan(local,
+                       rcu_dereference_protected(local->scan_sdata,
+                                                 lockdep_is_held(&local->mtx)),
+                       local->hw_scan_req);
+
                if (rc == 0)
                        return;
        }
@@ -394,7 +390,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local)
        if (!local->scan_req || local->scanning)
                return;
 
-       if (!ieee80211_can_scan(local, local->scan_sdata))
+       if (!ieee80211_can_scan(local,
+                               rcu_dereference_protected(
+                                       local->scan_sdata,
+                                       lockdep_is_held(&local->mtx))))
                return;
 
        ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
@@ -405,9 +404,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
                                            unsigned long *next_delay)
 {
        int i;
-       struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+       struct ieee80211_sub_if_data *sdata;
        enum ieee80211_band band = local->hw.conf.channel->band;
 
+       sdata = rcu_dereference_protected(local->scan_sdata,
+                                         lockdep_is_held(&local->mtx));;
+
        for (i = 0; i < local->scan_req->n_ssids; i++)
                ieee80211_send_probe_req(
                        sdata, NULL,
@@ -439,7 +441,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
        if (!ieee80211_can_scan(local, sdata)) {
                /* wait for the work to finish/time out */
                local->scan_req = req;
-               local->scan_sdata = sdata;
+               rcu_assign_pointer(local->scan_sdata, sdata);
                return 0;
        }
 
@@ -473,7 +475,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
        }
 
        local->scan_req = req;
-       local->scan_sdata = sdata;
+       rcu_assign_pointer(local->scan_sdata, sdata);
 
        if (local->ops->hw_scan) {
                __set_bit(SCAN_HW_SCANNING, &local->scanning);
@@ -533,7 +535,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
                ieee80211_recalc_idle(local);
 
                local->scan_req = NULL;
-               local->scan_sdata = NULL;
+               rcu_assign_pointer(local->scan_sdata, NULL);
        }
 
        return rc;
@@ -720,7 +722,8 @@ void ieee80211_scan_work(struct work_struct *work)
 
        mutex_lock(&local->mtx);
 
-       sdata = local->scan_sdata;
+       sdata = rcu_dereference_protected(local->scan_sdata,
+                                         lockdep_is_held(&local->mtx));
 
        /* When scanning on-channel, the first-callback means completed. */
        if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
@@ -741,7 +744,7 @@ void ieee80211_scan_work(struct work_struct *work)
                int rc;
 
                local->scan_req = NULL;
-               local->scan_sdata = NULL;
+               rcu_assign_pointer(local->scan_sdata, NULL);
 
                rc = __ieee80211_start_scan(sdata, req);
                if (rc) {
@@ -893,7 +896,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
 
        if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
                if (local->ops->cancel_hw_scan)
-                       drv_cancel_hw_scan(local, local->scan_sdata);
+                       drv_cancel_hw_scan(local,
+                               rcu_dereference_protected(local->scan_sdata,
+                                               lockdep_is_held(&local->mtx)));
                goto out;
        }
 
@@ -915,9 +920,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        int ret, i;
 
-       mutex_lock(&sdata->local->mtx);
+       mutex_lock(&local->mtx);
 
-       if (local->sched_scanning) {
+       if (rcu_access_pointer(local->sched_scan_sdata)) {
                ret = -EBUSY;
                goto out;
        }
@@ -928,6 +933,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        }
 
        for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+               if (!local->hw.wiphy->bands[i])
+                       continue;
+
                local->sched_scan_ies.ie[i] = kzalloc(2 +
                                                      IEEE80211_MAX_SSID_LEN +
                                                      local->scan_ies_len +
@@ -948,7 +956,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        ret = drv_sched_scan_start(local, sdata, req,
                                   &local->sched_scan_ies);
        if (ret == 0) {
-               local->sched_scanning = true;
+               rcu_assign_pointer(local->sched_scan_sdata, sdata);
                goto out;
        }
 
@@ -956,7 +964,7 @@ out_free:
        while (i > 0)
                kfree(local->sched_scan_ies.ie[--i]);
 out:
-       mutex_unlock(&sdata->local->mtx);
+       mutex_unlock(&local->mtx);
        return ret;
 }
 
@@ -965,22 +973,22 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_local *local = sdata->local;
        int ret = 0, i;
 
-       mutex_lock(&sdata->local->mtx);
+       mutex_lock(&local->mtx);
 
        if (!local->ops->sched_scan_stop) {
                ret = -ENOTSUPP;
                goto out;
        }
 
-       if (local->sched_scanning) {
+       if (rcu_access_pointer(local->sched_scan_sdata)) {
                for (i = 0; i < IEEE80211_NUM_BANDS; i++)
                        kfree(local->sched_scan_ies.ie[i]);
 
                drv_sched_scan_stop(local, sdata);
-               local->sched_scanning = false;
+               rcu_assign_pointer(local->sched_scan_sdata, NULL);
        }
 out:
-       mutex_unlock(&sdata->local->mtx);
+       mutex_unlock(&local->mtx);
 
        return ret;
 }
@@ -1004,7 +1012,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
 
        mutex_lock(&local->mtx);
 
-       if (!local->sched_scanning) {
+       if (!rcu_access_pointer(local->sched_scan_sdata)) {
                mutex_unlock(&local->mtx);
                return;
        }
@@ -1012,7 +1020,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
        for (i = 0; i < IEEE80211_NUM_BANDS; i++)
                kfree(local->sched_scan_ies.ie[i]);
 
-       local->sched_scanning = false;
+       rcu_assign_pointer(local->sched_scan_sdata, NULL);
 
        mutex_unlock(&local->mtx);
 
index 2ed2f27fe8a7db82e02905f4214c55ed23d631bd..8cd72914cdaf2f3540268920b1ab0969f687d330 100644 (file)
@@ -519,14 +519,19 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                u64 cookie = (unsigned long)skb;
                acked = info->flags & IEEE80211_TX_STAT_ACK;
 
+               /*
+                * TODO: When we have non-netdev frame TX,
+                * we cannot use skb->dev->ieee80211_ptr
+                */
+
                if (ieee80211_is_nullfunc(hdr->frame_control) ||
                    ieee80211_is_qos_nullfunc(hdr->frame_control))
                        cfg80211_probe_status(skb->dev, hdr->addr1,
                                              cookie, acked, GFP_ATOMIC);
                else
                        cfg80211_mgmt_tx_status(
-                               skb->dev, cookie, skb->data, skb->len,
-                               acked, GFP_ATOMIC);
+                               skb->dev->ieee80211_ptr, cookie, skb->data,
+                               skb->len, acked, GFP_ATOMIC);
        }
 
        if (unlikely(info->ack_frame_id)) {
index e1e9d10ec2e735efcb0dcddd9dc325d7113d572c..c6d33b55b2dfd51602d7fc40dcbbbb0ef6a0a451 100644 (file)
@@ -306,7 +306,8 @@ TRACE_EVENT(drv_bss_info_changed,
                __field(u8, dtimper)
                __field(u16, bcnint)
                __field(u16, assoc_cap)
-               __field(u64, timestamp)
+               __field(u64, sync_tsf)
+               __field(u32, sync_device_ts)
                __field(u32, basic_rates)
                __field(u32, changed)
                __field(bool, enable_beacon)
@@ -325,7 +326,8 @@ TRACE_EVENT(drv_bss_info_changed,
                __entry->dtimper = info->dtim_period;
                __entry->bcnint = info->beacon_int;
                __entry->assoc_cap = info->assoc_capability;
-               __entry->timestamp = info->last_tsf;
+               __entry->sync_tsf = info->sync_tsf;
+               __entry->sync_device_ts = info->sync_device_ts;
                __entry->basic_rates = info->basic_rates;
                __entry->enable_beacon = info->enable_beacon;
                __entry->ht_operation_mode = info->ht_operation_mode;
index c9d2175d15c1037a66af3086a37232f57b0f9b3e..b755e778b0c45ee11ac300b03e3cccd0243d2bbd 100644 (file)
@@ -523,7 +523,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 {
-       struct ieee80211_key *key = NULL;
+       struct ieee80211_key *key;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
 
@@ -542,16 +542,23 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
        else if (!is_multicast_ether_addr(hdr->addr1) &&
                 (key = rcu_dereference(tx->sdata->default_unicast_key)))
                tx->key = key;
-       else if (tx->sdata->drop_unencrypted &&
-                (tx->skb->protocol != tx->sdata->control_port_protocol) &&
-                !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
-                (!ieee80211_is_robust_mgmt_frame(hdr) ||
-                 (ieee80211_is_action(hdr->frame_control) &&
-                  tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) {
+       else if (info->flags & IEEE80211_TX_CTL_INJECTED)
+               tx->key = NULL;
+       else if (!tx->sdata->drop_unencrypted)
+               tx->key = NULL;
+       else if (tx->skb->protocol == tx->sdata->control_port_protocol)
+               tx->key = NULL;
+       else if (ieee80211_is_robust_mgmt_frame(hdr) &&
+                !(ieee80211_is_action(hdr->frame_control) &&
+                  tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
+               tx->key = NULL;
+       else if (ieee80211_is_mgmt(hdr->frame_control) &&
+                !ieee80211_is_robust_mgmt_frame(hdr))
+               tx->key = NULL;
+       else {
                I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
                return TX_DROP;
-       } else
-               tx->key = NULL;
+       }
 
        if (tx->key) {
                bool skip_hw = false;
index 64493a7bef1a388a1f7f2a9aca8d13b7834d52fb..39b82fee4904784c87a635026e8ae0b7e2a4318d 100644 (file)
@@ -529,6 +529,11 @@ void ieee80211_iterate_active_interfaces(
                                 &sdata->vif);
        }
 
+       sdata = rcu_dereference_protected(local->monitor_sdata,
+                                         lockdep_is_held(&local->iflist_mtx));
+       if (sdata)
+               iterator(data, sdata->vif.addr, &sdata->vif);
+
        mutex_unlock(&local->iflist_mtx);
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
@@ -557,6 +562,10 @@ void ieee80211_iterate_active_interfaces_atomic(
                                 &sdata->vif);
        }
 
+       sdata = rcu_dereference(local->monitor_sdata);
+       if (sdata)
+               iterator(data, sdata->vif.addr, &sdata->vif);
+
        rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
@@ -999,6 +1008,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
        int ext_rates_len;
 
        sband = local->hw.wiphy->bands[band];
+       if (WARN_ON_ONCE(!sband))
+               return 0;
 
        pos = buffer;
 
index 434c56b92c3c1ea458a2e2f1a97f5e9d964fdfaf..1cc4b7cc7372260eedc9872115a9ff2b81563279 100644 (file)
@@ -103,15 +103,13 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
 }
 
 void
-cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
-                       struct wireless_dev *wdev,
+cfg80211_get_chan_state(struct wireless_dev *wdev,
                        struct ieee80211_channel **chan,
                        enum cfg80211_chan_mode *chanmode)
 {
        *chan = NULL;
        *chanmode = CHAN_MODE_UNDEFINED;
 
-       ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
 
        if (!netif_running(wdev->netdev))
index eb60410ae58879b48c96d663f5926aaaaf1c47e9..0557bb159025e0679966a468a5ada227ee54e9c7 100644 (file)
@@ -176,7 +176,9 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
        if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
                return -EOPNOTSUPP;
 
-       list_for_each_entry(wdev, &rdev->netdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               if (!wdev->netdev)
+                       continue;
                wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
                err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
                if (err)
@@ -188,8 +190,10 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
                /* failed -- clean up to old netns */
                net = wiphy_net(&rdev->wiphy);
 
-               list_for_each_entry_continue_reverse(wdev, &rdev->netdev_list,
+               list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list,
                                                     list) {
+                       if (!wdev->netdev)
+                               continue;
                        wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
                        err = dev_change_net_namespace(wdev->netdev, net,
                                                        "wlan%d");
@@ -226,8 +230,9 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
        rtnl_lock();
        mutex_lock(&rdev->devlist_mtx);
 
-       list_for_each_entry(wdev, &rdev->netdev_list, list)
-               dev_close(wdev->netdev);
+       list_for_each_entry(wdev, &rdev->wdev_list, list)
+               if (wdev->netdev)
+                       dev_close(wdev->netdev);
 
        mutex_unlock(&rdev->devlist_mtx);
        rtnl_unlock();
@@ -304,7 +309,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
        mutex_init(&rdev->mtx);
        mutex_init(&rdev->devlist_mtx);
        mutex_init(&rdev->sched_scan_mtx);
-       INIT_LIST_HEAD(&rdev->netdev_list);
+       INIT_LIST_HEAD(&rdev->wdev_list);
        spin_lock_init(&rdev->bss_lock);
        INIT_LIST_HEAD(&rdev->bss_list);
        INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
@@ -622,7 +627,7 @@ void wiphy_unregister(struct wiphy *wiphy)
                __count == 0; }));
 
        mutex_lock(&rdev->devlist_mtx);
-       BUG_ON(!list_empty(&rdev->netdev_list));
+       BUG_ON(!list_empty(&rdev->wdev_list));
        mutex_unlock(&rdev->devlist_mtx);
 
        /*
@@ -703,7 +708,7 @@ static void wdev_cleanup_work(struct work_struct *work)
 
        cfg80211_lock_rdev(rdev);
 
-       if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == wdev->netdev)) {
+       if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
                rdev->scan_req->aborted = true;
                ___cfg80211_scan_done(rdev, true);
        }
@@ -774,8 +779,9 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
 
        has_monitors_only_new = cfg80211_has_monitors_only(rdev);
        if (has_monitors_only_new != has_monitors_only_old) {
-               rdev->ops->set_monitor_enabled(&rdev->wiphy,
-                                              has_monitors_only_new);
+               if (rdev->ops->set_monitor_enabled)
+                       rdev->ops->set_monitor_enabled(&rdev->wiphy,
+                                                      has_monitors_only_new);
 
                if (!has_monitors_only_new) {
                        rdev->monitor_channel = NULL;
@@ -820,7 +826,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                spin_lock_init(&wdev->mgmt_registrations_lock);
 
                mutex_lock(&rdev->devlist_mtx);
-               list_add_rcu(&wdev->list, &rdev->netdev_list);
+               wdev->identifier = ++rdev->wdev_id;
+               list_add_rcu(&wdev->list, &rdev->wdev_list);
                rdev->devlist_generation++;
                /* can only change netns with wiphy */
                dev->features |= NETIF_F_NETNS_LOCAL;
index 377dc394f48c99ff1e4cec0df6929ebecc876649..bac97da751dfa265088c17e622645cac8d5744ad 100644 (file)
@@ -47,11 +47,11 @@ struct cfg80211_registered_device {
        /* wiphy index, internal only */
        int wiphy_idx;
 
-       /* associate netdev list */
+       /* associated wireless interfaces */
        struct mutex devlist_mtx;
        /* protected by devlist_mtx or RCU */
-       struct list_head netdev_list;
-       int devlist_generation;
+       struct list_head wdev_list;
+       int devlist_generation, wdev_id;
        int opencount; /* also protected by devlist_mtx */
        wait_queue_head_t dev_wait;
 
@@ -372,7 +372,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
 void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
-                         struct net_device *dev,
+                         struct wireless_dev *wdev,
                          struct ieee80211_channel *chan, bool offchan,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
@@ -463,8 +463,7 @@ cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
 }
 
 void
-cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
-                       struct wireless_dev *wdev,
+cfg80211_get_chan_state(struct wireless_dev *wdev,
                        struct ieee80211_channel **chan,
                        enum cfg80211_chan_mode *chanmode);
 
index d4fece3bb18a8215ce30fd55e748e7f59b5bcee1..abe9f82d5a82d645e59848a2a97ca983ebc8b990 100644 (file)
@@ -567,29 +567,28 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
        }
 }
 
-void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie,
+void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
                               struct ieee80211_channel *chan,
                               enum nl80211_channel_type channel_type,
                               unsigned int duration, gfp_t gfp)
 {
-       struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+       struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
-       nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type,
+       nl80211_send_remain_on_channel(rdev, wdev, cookie, chan, channel_type,
                                       duration, gfp);
 }
 EXPORT_SYMBOL(cfg80211_ready_on_channel);
 
-void cfg80211_remain_on_channel_expired(struct net_device *dev,
-                                       u64 cookie,
+void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
                                        struct ieee80211_channel *chan,
                                        enum nl80211_channel_type channel_type,
                                        gfp_t gfp)
 {
-       struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+       struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
-       nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan,
+       nl80211_send_remain_on_channel_cancel(rdev, wdev, cookie, chan,
                                              channel_type, gfp);
 }
 EXPORT_SYMBOL(cfg80211_remain_on_channel_expired);
@@ -678,8 +677,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
        list_add(&nreg->list, &wdev->mgmt_registrations);
 
        if (rdev->ops->mgmt_frame_register)
-               rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
-                                              frame_type, true);
+               rdev->ops->mgmt_frame_register(wiphy, wdev, frame_type, true);
 
  out:
        spin_unlock_bh(&wdev->mgmt_registrations_lock);
@@ -702,7 +700,7 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
                if (rdev->ops->mgmt_frame_register) {
                        u16 frame_type = le16_to_cpu(reg->frame_type);
 
-                       rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
+                       rdev->ops->mgmt_frame_register(wiphy, wdev,
                                                       frame_type, false);
                }
 
@@ -731,14 +729,14 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
 }
 
 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
-                         struct net_device *dev,
+                         struct wireless_dev *wdev,
                          struct ieee80211_channel *chan, bool offchan,
                          enum nl80211_channel_type channel_type,
                          bool channel_type_valid, unsigned int wait,
                          const u8 *buf, size_t len, bool no_cck,
                          bool dont_wait_for_ack, u64 *cookie)
 {
-       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct net_device *dev = wdev->netdev;
        const struct ieee80211_mgmt *mgmt;
        u16 stype;
 
@@ -825,16 +823,15 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                return -EINVAL;
 
        /* Transmit the Action frame as requested by user space */
-       return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan,
+       return rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
                                  channel_type, channel_type_valid,
                                  wait, buf, len, no_cck, dont_wait_for_ack,
                                  cookie);
 }
 
-bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
+bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
                      const u8 *buf, size_t len, gfp_t gfp)
 {
-       struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
        struct cfg80211_mgmt_registration *reg;
@@ -871,7 +868,7 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
                /* found match! */
 
                /* Indicate the received Action frame to user space */
-               if (nl80211_send_mgmt(rdev, dev, reg->nlpid,
+               if (nl80211_send_mgmt(rdev, wdev, reg->nlpid,
                                      freq, sig_mbm,
                                      buf, len, gfp))
                        continue;
@@ -886,15 +883,14 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm,
 }
 EXPORT_SYMBOL(cfg80211_rx_mgmt);
 
-void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie,
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
                             const u8 *buf, size_t len, bool ack, gfp_t gfp)
 {
-       struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
        /* Indicate TX status of the Action frame to user space */
-       nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp);
+       nl80211_send_mgmt_tx_status(rdev, wdev, cookie, buf, len, ack, gfp);
 }
 EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
 
index 2a5cdb60bc6e0ba15003592149bb10d56d4d0c4d..6472c7f928dc1330a2d7e1d368a012eef78ae48b 100644 (file)
@@ -46,28 +46,60 @@ static struct genl_family nl80211_fam = {
        .post_doit = nl80211_post_doit,
 };
 
-/* internal helper: get rdev and dev */
-static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
-                                  struct cfg80211_registered_device **rdev,
-                                  struct net_device **dev)
+/* returns ERR_PTR values */
+static struct wireless_dev *
+__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
 {
-       int ifindex;
+       struct cfg80211_registered_device *rdev;
+       struct wireless_dev *result = NULL;
+       bool have_ifidx = attrs[NL80211_ATTR_IFINDEX];
+       bool have_wdev_id = attrs[NL80211_ATTR_WDEV];
+       u64 wdev_id;
+       int wiphy_idx = -1;
+       int ifidx = -1;
 
-       if (!attrs[NL80211_ATTR_IFINDEX])
-               return -EINVAL;
+       assert_cfg80211_lock();
 
-       ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
-       *dev = dev_get_by_index(netns, ifindex);
-       if (!*dev)
-               return -ENODEV;
+       if (!have_ifidx && !have_wdev_id)
+               return ERR_PTR(-EINVAL);
 
-       *rdev = cfg80211_get_dev_from_ifindex(netns, ifindex);
-       if (IS_ERR(*rdev)) {
-               dev_put(*dev);
-               return PTR_ERR(*rdev);
+       if (have_ifidx)
+               ifidx = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
+       if (have_wdev_id) {
+               wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
+               wiphy_idx = wdev_id >> 32;
        }
 
-       return 0;
+       list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+               struct wireless_dev *wdev;
+
+               if (wiphy_net(&rdev->wiphy) != netns)
+                       continue;
+
+               if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
+                       continue;
+
+               mutex_lock(&rdev->devlist_mtx);
+               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+                       if (have_ifidx && wdev->netdev &&
+                           wdev->netdev->ifindex == ifidx) {
+                               result = wdev;
+                               break;
+                       }
+                       if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
+                               result = wdev;
+                               break;
+                       }
+               }
+               mutex_unlock(&rdev->devlist_mtx);
+
+               if (result)
+                       break;
+       }
+
+       if (result)
+               return result;
+       return ERR_PTR(-ENODEV);
 }
 
 static struct cfg80211_registered_device *
@@ -79,13 +111,40 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
        assert_cfg80211_lock();
 
        if (!attrs[NL80211_ATTR_WIPHY] &&
-           !attrs[NL80211_ATTR_IFINDEX])
+           !attrs[NL80211_ATTR_IFINDEX] &&
+           !attrs[NL80211_ATTR_WDEV])
                return ERR_PTR(-EINVAL);
 
        if (attrs[NL80211_ATTR_WIPHY])
                rdev = cfg80211_rdev_by_wiphy_idx(
                                nla_get_u32(attrs[NL80211_ATTR_WIPHY]));
 
+       if (attrs[NL80211_ATTR_WDEV]) {
+               u64 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]);
+               struct wireless_dev *wdev;
+               bool found = false;
+
+               tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
+               if (tmp) {
+                       /* make sure wdev exists */
+                       mutex_lock(&tmp->devlist_mtx);
+                       list_for_each_entry(wdev, &tmp->wdev_list, list) {
+                               if (wdev->identifier != (u32)wdev_id)
+                                       continue;
+                               found = true;
+                               break;
+                       }
+                       mutex_unlock(&tmp->devlist_mtx);
+
+                       if (!found)
+                               tmp = NULL;
+
+                       if (rdev && tmp != rdev)
+                               return ERR_PTR(-EINVAL);
+                       rdev = tmp;
+               }
+       }
+
        if (attrs[NL80211_ATTR_IFINDEX]) {
                int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
                netdev = dev_get_by_index(netns, ifindex);
@@ -294,6 +353,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
        [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
        [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+       [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
 };
 
 /* policy for the key attributes */
@@ -1668,22 +1728,32 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
        return result;
 }
 
+static inline u64 wdev_id(struct wireless_dev *wdev)
+{
+       return (u64)wdev->identifier |
+              ((u64)wiphy_to_dev(wdev->wiphy)->wiphy_idx << 32);
+}
 
 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
                              struct cfg80211_registered_device *rdev,
-                             struct net_device *dev)
+                             struct wireless_dev *wdev)
 {
+       struct net_device *dev = wdev->netdev;
        void *hdr;
 
        hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
        if (!hdr)
                return -1;
 
-       if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
-           nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) ||
-           nla_put_u32(msg, NL80211_ATTR_IFTYPE,
-                       dev->ieee80211_ptr->iftype) ||
+       if (dev &&
+           (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+            nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) ||
+            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dev->dev_addr)))
+               goto nla_put_failure;
+
+       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+           nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
+           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
            nla_put_u32(msg, NL80211_ATTR_GENERATION,
                        rdev->devlist_generation ^
                        (cfg80211_rdev_list_generation << 2)))
@@ -1724,14 +1794,14 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
                if_idx = 0;
 
                mutex_lock(&rdev->devlist_mtx);
-               list_for_each_entry(wdev, &rdev->netdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wdev_list, list) {
                        if (if_idx < if_start) {
                                if_idx++;
                                continue;
                        }
                        if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
                                               cb->nlh->nlmsg_seq, NLM_F_MULTI,
-                                              rdev, wdev->netdev) < 0) {
+                                              rdev, wdev) < 0) {
                                mutex_unlock(&rdev->devlist_mtx);
                                goto out;
                        }
@@ -1754,14 +1824,14 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
 {
        struct sk_buff *msg;
        struct cfg80211_registered_device *dev = info->user_ptr[0];
-       struct net_device *netdev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg)
                return -ENOMEM;
 
        if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
-                              dev, netdev) < 0) {
+                              dev, wdev) < 0) {
                nlmsg_free(msg);
                return -ENOBUFS;
        }
@@ -1901,7 +1971,8 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct vif_params params;
-       struct net_device *dev;
+       struct wireless_dev *wdev;
+       struct sk_buff *msg;
        int err;
        enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
        u32 flags;
@@ -1928,19 +1999,23 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                        return err;
        }
 
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
        err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
                                  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
                                  &flags);
-       dev = rdev->ops->add_virtual_intf(&rdev->wiphy,
+       wdev = rdev->ops->add_virtual_intf(&rdev->wiphy,
                nla_data(info->attrs[NL80211_ATTR_IFNAME]),
                type, err ? NULL : &flags, &params);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
+       if (IS_ERR(wdev)) {
+               nlmsg_free(msg);
+               return PTR_ERR(wdev);
+       }
 
        if (type == NL80211_IFTYPE_MESH_POINT &&
            info->attrs[NL80211_ATTR_MESH_ID]) {
-               struct wireless_dev *wdev = dev->ieee80211_ptr;
-
                wdev_lock(wdev);
                BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
                             IEEE80211_MAX_MESH_ID_LEN);
@@ -1951,18 +2026,34 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                wdev_unlock(wdev);
        }
 
-       return 0;
+       if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
+                              rdev, wdev) < 0) {
+               nlmsg_free(msg);
+               return -ENOBUFS;
+       }
+
+       return genlmsg_reply(msg, info);
 }
 
 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
 
        if (!rdev->ops->del_virtual_intf)
                return -EOPNOTSUPP;
 
-       return rdev->ops->del_virtual_intf(&rdev->wiphy, dev);
+       /*
+        * If we remove a wireless device without a netdev then clear
+        * user_ptr[1] so that nl80211_post_doit won't dereference it
+        * to check if it needs to do dev_put(). Otherwise it crashes
+        * since the wdev has been freed, unlike with a netdev where
+        * we need the dev_put() for the netdev to really be freed.
+        */
+       if (!wdev->netdev)
+               info->user_ptr[1] = NULL;
+
+       return rdev->ops->del_virtual_intf(&rdev->wiphy, wdev);
 }
 
 static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -2350,7 +2441,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
 
        mutex_lock(&rdev->devlist_mtx);
 
-       list_for_each_entry(wdev, &rdev->netdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO)
                        continue;
@@ -4039,7 +4130,7 @@ static int validate_scan_freqs(struct nlattr *freqs)
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
        struct cfg80211_scan_request *request;
        struct nlattr *attr;
        struct wiphy *wiphy;
@@ -4199,15 +4290,16 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        request->no_cck =
                nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
 
-       request->dev = dev;
+       request->wdev = wdev;
        request->wiphy = &rdev->wiphy;
 
        rdev->scan_req = request;
-       err = rdev->ops->scan(&rdev->wiphy, dev, request);
+       err = rdev->ops->scan(&rdev->wiphy, request);
 
        if (!err) {
-               nl80211_send_scan_start(rdev, dev);
-               dev_hold(dev);
+               nl80211_send_scan_start(rdev, wdev);
+               if (wdev->netdev)
+                       dev_hold(wdev->netdev);
        } else {
  out_free:
                rdev->scan_req = NULL;
@@ -5685,7 +5777,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
                                     struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
        struct ieee80211_channel *chan;
        struct sk_buff *msg;
        void *hdr;
@@ -5733,7 +5825,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
                goto free_msg;
        }
 
-       err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan,
+       err = rdev->ops->remain_on_channel(&rdev->wiphy, wdev, chan,
                                           channel_type, duration, &cookie);
 
        if (err)
@@ -5757,7 +5849,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
                                            struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
        u64 cookie;
 
        if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -5768,7 +5860,7 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
 
        cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
 
-       return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie);
+       return rdev->ops->cancel_remain_on_channel(&rdev->wiphy, wdev, cookie);
 }
 
 static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
@@ -5917,7 +6009,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
 static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
        u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION;
 
        if (!info->attrs[NL80211_ATTR_FRAME_MATCH])
@@ -5926,21 +6018,24 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_FRAME_TYPE])
                frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]);
 
-       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_P2P_GO:
+               break;
+       default:
                return -EOPNOTSUPP;
+       }
 
        /* not much point in registering if we can't reply */
        if (!rdev->ops->mgmt_tx)
                return -EOPNOTSUPP;
 
-       return cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid,
-                       frame_type,
+       return cfg80211_mlme_register_mgmt(wdev, info->snd_pid, frame_type,
                        nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]),
                        nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
 }
@@ -5948,7 +6043,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
 static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
        struct ieee80211_channel *chan;
        enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
        bool channel_type_valid = false;
@@ -5969,14 +6064,18 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->mgmt_tx)
                return -EOPNOTSUPP;
 
-       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_P2P_GO:
+               break;
+       default:
                return -EOPNOTSUPP;
+       }
 
        if (info->attrs[NL80211_ATTR_DURATION]) {
                if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
@@ -6025,7 +6124,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
-       err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type,
+       err = cfg80211_mlme_mgmt_tx(rdev, wdev, chan, offchan, channel_type,
                                    channel_type_valid, wait,
                                    nla_data(info->attrs[NL80211_ATTR_FRAME]),
                                    nla_len(info->attrs[NL80211_ATTR_FRAME]),
@@ -6053,7 +6152,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = info->user_ptr[1];
        u64 cookie;
 
        if (!info->attrs[NL80211_ATTR_COOKIE])
@@ -6062,17 +6161,21 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
        if (!rdev->ops->mgmt_tx_cancel_wait)
                return -EOPNOTSUPP;
 
-       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_P2P_GO:
+               break;
+       default:
                return -EOPNOTSUPP;
+       }
 
        cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
 
-       return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, dev, cookie);
+       return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, wdev, cookie);
 }
 
 static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info)
@@ -6655,13 +6758,17 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
 #define NL80211_FLAG_CHECK_NETDEV_UP   0x08
 #define NL80211_FLAG_NEED_NETDEV_UP    (NL80211_FLAG_NEED_NETDEV |\
                                         NL80211_FLAG_CHECK_NETDEV_UP)
+#define NL80211_FLAG_NEED_WDEV         0x10
+/* If a netdev is associated, it must be UP */
+#define NL80211_FLAG_NEED_WDEV_UP      (NL80211_FLAG_NEED_WDEV |\
+                                        NL80211_FLAG_CHECK_NETDEV_UP)
 
 static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
                            struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev;
+       struct wireless_dev *wdev;
        struct net_device *dev;
-       int err;
        bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
 
        if (rtnl)
@@ -6675,24 +6782,51 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
                        return PTR_ERR(rdev);
                }
                info->user_ptr[0] = rdev;
-       } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
-               err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs,
-                                             &rdev, &dev);
-               if (err) {
+       } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
+                  ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
+               mutex_lock(&cfg80211_mutex);
+               wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
+                                                 info->attrs);
+               if (IS_ERR(wdev)) {
+                       mutex_unlock(&cfg80211_mutex);
                        if (rtnl)
                                rtnl_unlock();
-                       return err;
+                       return PTR_ERR(wdev);
                }
-               if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
-                   !netif_running(dev)) {
-                       cfg80211_unlock_rdev(rdev);
-                       dev_put(dev);
-                       if (rtnl)
-                               rtnl_unlock();
-                       return -ENETDOWN;
+
+               dev = wdev->netdev;
+               rdev = wiphy_to_dev(wdev->wiphy);
+
+               if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
+                       if (!dev) {
+                               mutex_unlock(&cfg80211_mutex);
+                               if (rtnl)
+                                       rtnl_unlock();
+                               return -EINVAL;
+                       }
+
+                       info->user_ptr[1] = dev;
+               } else {
+                       info->user_ptr[1] = wdev;
                }
+
+               if (dev) {
+                       if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
+                           !netif_running(dev)) {
+                               mutex_unlock(&cfg80211_mutex);
+                               if (rtnl)
+                                       rtnl_unlock();
+                               return -ENETDOWN;
+                       }
+
+                       dev_hold(dev);
+               }
+
+               cfg80211_lock_rdev(rdev);
+
+               mutex_unlock(&cfg80211_mutex);
+
                info->user_ptr[0] = rdev;
-               info->user_ptr[1] = dev;
        }
 
        return 0;
@@ -6703,8 +6837,16 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
 {
        if (info->user_ptr[0])
                cfg80211_unlock_rdev(info->user_ptr[0]);
-       if (info->user_ptr[1])
-               dev_put(info->user_ptr[1]);
+       if (info->user_ptr[1]) {
+               if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
+                       struct wireless_dev *wdev = info->user_ptr[1];
+
+                       if (wdev->netdev)
+                               dev_put(wdev->netdev);
+               } else {
+                       dev_put(info->user_ptr[1]);
+               }
+       }
        if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
                rtnl_unlock();
 }
@@ -6731,7 +6873,7 @@ static struct genl_ops nl80211_ops[] = {
                .dumpit = nl80211_dump_interface,
                .policy = nl80211_policy,
                /* can be retrieved by unprivileged users */
-               .internal_flags = NL80211_FLAG_NEED_NETDEV,
+               .internal_flags = NL80211_FLAG_NEED_WDEV,
        },
        {
                .cmd = NL80211_CMD_SET_INTERFACE,
@@ -6754,7 +6896,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_del_interface,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_WDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -6925,7 +7067,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_trigger_scan,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+               .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7066,7 +7208,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_remain_on_channel,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+               .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7074,7 +7216,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_cancel_remain_on_channel,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+               .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7090,7 +7232,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_register_mgmt,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV |
+               .internal_flags = NL80211_FLAG_NEED_WDEV |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7098,7 +7240,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_tx_mgmt,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+               .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7106,7 +7248,7 @@ static struct genl_ops nl80211_ops[] = {
                .doit = nl80211_tx_mgmt_cancel_wait,
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+               .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
        {
@@ -7317,7 +7459,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
 
 static int nl80211_send_scan_msg(struct sk_buff *msg,
                                 struct cfg80211_registered_device *rdev,
-                                struct net_device *netdev,
+                                struct wireless_dev *wdev,
                                 u32 pid, u32 seq, int flags,
                                 u32 cmd)
 {
@@ -7328,7 +7470,9 @@ static int nl80211_send_scan_msg(struct sk_buff *msg,
                return -1;
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
+           (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+                                        wdev->netdev->ifindex)) ||
+           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
                goto nla_put_failure;
 
        /* ignore errors and send incomplete event anyway */
@@ -7365,7 +7509,7 @@ nl80211_send_sched_scan_msg(struct sk_buff *msg,
 }
 
 void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
-                            struct net_device *netdev)
+                            struct wireless_dev *wdev)
 {
        struct sk_buff *msg;
 
@@ -7373,7 +7517,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
        if (!msg)
                return;
 
-       if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
                                  NL80211_CMD_TRIGGER_SCAN) < 0) {
                nlmsg_free(msg);
                return;
@@ -7384,7 +7528,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
 }
 
 void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
-                           struct net_device *netdev)
+                           struct wireless_dev *wdev)
 {
        struct sk_buff *msg;
 
@@ -7392,7 +7536,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
        if (!msg)
                return;
 
-       if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
                                  NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
                nlmsg_free(msg);
                return;
@@ -7403,7 +7547,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
 }
 
 void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
-                              struct net_device *netdev)
+                              struct wireless_dev *wdev)
 {
        struct sk_buff *msg;
 
@@ -7411,7 +7555,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
        if (!msg)
                return;
 
-       if (nl80211_send_scan_msg(msg, rdev, netdev, 0, 0, 0,
+       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
                                  NL80211_CMD_SCAN_ABORTED) < 0) {
                nlmsg_free(msg);
                return;
@@ -7934,7 +8078,7 @@ nla_put_failure:
 
 static void nl80211_send_remain_on_chan_event(
        int cmd, struct cfg80211_registered_device *rdev,
-       struct net_device *netdev, u64 cookie,
+       struct wireless_dev *wdev, u64 cookie,
        struct ieee80211_channel *chan,
        enum nl80211_channel_type channel_type,
        unsigned int duration, gfp_t gfp)
@@ -7953,7 +8097,9 @@ static void nl80211_send_remain_on_chan_event(
        }
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+                                        wdev->netdev->ifindex)) ||
+           nla_put_u32(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type) ||
            nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
@@ -7975,23 +8121,24 @@ static void nl80211_send_remain_on_chan_event(
 }
 
 void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
-                                   struct net_device *netdev, u64 cookie,
+                                   struct wireless_dev *wdev, u64 cookie,
                                    struct ieee80211_channel *chan,
                                    enum nl80211_channel_type channel_type,
                                    unsigned int duration, gfp_t gfp)
 {
        nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL,
-                                         rdev, netdev, cookie, chan,
+                                         rdev, wdev, cookie, chan,
                                          channel_type, duration, gfp);
 }
 
 void nl80211_send_remain_on_channel_cancel(
-       struct cfg80211_registered_device *rdev, struct net_device *netdev,
+       struct cfg80211_registered_device *rdev,
+       struct wireless_dev *wdev,
        u64 cookie, struct ieee80211_channel *chan,
        enum nl80211_channel_type channel_type, gfp_t gfp)
 {
        nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
-                                         rdev, netdev, cookie, chan,
+                                         rdev, wdev, cookie, chan,
                                          channel_type, 0, gfp);
 }
 
@@ -8105,10 +8252,11 @@ bool nl80211_unexpected_4addr_frame(struct net_device *dev,
 }
 
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
-                     struct net_device *netdev, u32 nlpid,
+                     struct wireless_dev *wdev, u32 nlpid,
                      int freq, int sig_dbm,
                      const u8 *buf, size_t len, gfp_t gfp)
 {
+       struct net_device *netdev = wdev->netdev;
        struct sk_buff *msg;
        void *hdr;
 
@@ -8123,7 +8271,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
        }
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+                                       netdev->ifindex)) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
            (sig_dbm &&
             nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
@@ -8141,10 +8290,11 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 }
 
 void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
-                                struct net_device *netdev, u64 cookie,
+                                struct wireless_dev *wdev, u64 cookie,
                                 const u8 *buf, size_t len, bool ack,
                                 gfp_t gfp)
 {
+       struct net_device *netdev = wdev->netdev;
        struct sk_buff *msg;
        void *hdr;
 
@@ -8159,7 +8309,8 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
        }
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+                                  netdev->ifindex)) ||
            nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
            nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
            (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
@@ -8483,7 +8634,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
        rcu_read_lock();
 
        list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
-               list_for_each_entry_rcu(wdev, &rdev->netdev_list, list)
+               list_for_each_entry_rcu(wdev, &rdev->wdev_list, list)
                        cfg80211_mlme_unregister_socket(wdev, notify->pid);
                if (rdev->ap_beacons_nlpid == notify->pid)
                        rdev->ap_beacons_nlpid = 0;
index 01a1122c3b336898d3ad8856d2dc997837820e88..89ce99675e61352236c32a56cfc0ba0138339496 100644 (file)
@@ -7,11 +7,11 @@ int nl80211_init(void);
 void nl80211_exit(void);
 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
 void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
-                            struct net_device *netdev);
+                            struct wireless_dev *wdev);
 void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
-                           struct net_device *netdev);
+                           struct wireless_dev *wdev);
 void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
-                              struct net_device *netdev);
+                              struct wireless_dev *wdev);
 void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
                             struct net_device *netdev, u32 cmd);
 void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
@@ -74,13 +74,13 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
                             gfp_t gfp);
 
 void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev,
-                                   struct net_device *netdev,
-                                   u64 cookie,
+                                   struct wireless_dev *wdev, u64 cookie,
                                    struct ieee80211_channel *chan,
                                    enum nl80211_channel_type channel_type,
                                    unsigned int duration, gfp_t gfp);
 void nl80211_send_remain_on_channel_cancel(
-       struct cfg80211_registered_device *rdev, struct net_device *netdev,
+       struct cfg80211_registered_device *rdev,
+       struct wireless_dev *wdev,
        u64 cookie, struct ieee80211_channel *chan,
        enum nl80211_channel_type channel_type, gfp_t gfp);
 
@@ -92,11 +92,11 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
                                gfp_t gfp);
 
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
-                     struct net_device *netdev, u32 nlpid,
+                     struct wireless_dev *wdev, u32 nlpid,
                      int freq, int sig_dbm,
                      const u8 *buf, size_t len, gfp_t gfp);
 void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
-                                struct net_device *netdev, u64 cookie,
+                                struct wireless_dev *wdev, u64 cookie,
                                 const u8 *buf, size_t len, bool ack,
                                 gfp_t gfp);
 
index af2b1caa37fab51adc699f0ce13ddbefa0d64e83..848523a2b22f02c9a8975ff942073c0794671b54 100644 (file)
@@ -23,7 +23,7 @@
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
 {
        struct cfg80211_scan_request *request;
-       struct net_device *dev;
+       struct wireless_dev *wdev;
 #ifdef CONFIG_CFG80211_WEXT
        union iwreq_data wrqu;
 #endif
@@ -35,29 +35,31 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
        if (!request)
                return;
 
-       dev = request->dev;
+       wdev = request->wdev;
 
        /*
         * This must be before sending the other events!
         * Otherwise, wpa_supplicant gets completely confused with
         * wext events.
         */
-       cfg80211_sme_scan_done(dev);
+       if (wdev->netdev)
+               cfg80211_sme_scan_done(wdev->netdev);
 
        if (request->aborted)
-               nl80211_send_scan_aborted(rdev, dev);
+               nl80211_send_scan_aborted(rdev, wdev);
        else
-               nl80211_send_scan_done(rdev, dev);
+               nl80211_send_scan_done(rdev, wdev);
 
 #ifdef CONFIG_CFG80211_WEXT
-       if (!request->aborted) {
+       if (wdev->netdev && !request->aborted) {
                memset(&wrqu, 0, sizeof(wrqu));
 
-               wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+               wireless_send_event(wdev->netdev, SIOCGIWSCAN, &wrqu, NULL);
        }
 #endif
 
-       dev_put(dev);
+       if (wdev->netdev)
+               dev_put(wdev->netdev);
 
        rdev->scan_req = NULL;
 
@@ -955,7 +957,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        }
 
        creq->wiphy = wiphy;
-       creq->dev = dev;
+       creq->wdev = dev->ieee80211_ptr;
        /* SSIDs come after channels */
        creq->ssids = (void *)&creq->channels[n_channels];
        creq->n_channels = n_channels;
@@ -1024,12 +1026,12 @@ int cfg80211_wext_siwscan(struct net_device *dev,
                        creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
 
        rdev->scan_req = creq;
-       err = rdev->ops->scan(wiphy, dev, creq);
+       err = rdev->ops->scan(wiphy, creq);
        if (err) {
                rdev->scan_req = NULL;
                /* creq will be freed below */
        } else {
-               nl80211_send_scan_start(rdev, dev);
+               nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
                /* creq now owned by driver */
                creq = NULL;
                dev_hold(dev);
index f7e937ff897893a2dff84efcf9d8a9422aebe3b0..6f39cb808302380e05fa70d9a68925f7a35dcae3 100644 (file)
@@ -51,7 +51,7 @@ static bool cfg80211_is_all_idle(void)
         */
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                cfg80211_lock_rdev(rdev);
-               list_for_each_entry(wdev, &rdev->netdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wdev_list, list) {
                        wdev_lock(wdev);
                        if (wdev->sme_state != CFG80211_SME_IDLE)
                                is_all_idle = false;
@@ -136,15 +136,15 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
                wdev->conn->params.ssid_len);
        request->ssids[0].ssid_len = wdev->conn->params.ssid_len;
 
-       request->dev = wdev->netdev;
+       request->wdev = wdev;
        request->wiphy = &rdev->wiphy;
 
        rdev->scan_req = request;
 
-       err = rdev->ops->scan(wdev->wiphy, wdev->netdev, request);
+       err = rdev->ops->scan(wdev->wiphy, request);
        if (!err) {
                wdev->conn->state = CFG80211_CONN_SCANNING;
-               nl80211_send_scan_start(rdev, wdev->netdev);
+               nl80211_send_scan_start(rdev, wdev);
                dev_hold(wdev->netdev);
        } else {
                rdev->scan_req = NULL;
@@ -221,7 +221,7 @@ void cfg80211_conn_work(struct work_struct *work)
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
 
-       list_for_each_entry(wdev, &rdev->netdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wdev_list, list) {
                wdev_lock(wdev);
                if (!netif_running(wdev->netdev)) {
                        wdev_unlock(wdev);
index e31f1dba79ecc73021f2451bc35b29161845deab..26f8cd30f712dc190d9e207e4dff989a75106c66 100644 (file)
@@ -793,7 +793,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
 
        mutex_lock(&rdev->devlist_mtx);
 
-       list_for_each_entry(wdev, &rdev->netdev_list, list)
+       list_for_each_entry(wdev, &rdev->wdev_list, list)
                cfg80211_process_wdev_events(wdev);
 
        mutex_unlock(&rdev->devlist_mtx);
@@ -994,7 +994,7 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 
        mutex_lock(&rdev->devlist_mtx);
 
-       list_for_each_entry(wdev, &rdev->netdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (!wdev->beacon_interval)
                        continue;
                if (wdev->beacon_interval != beacon_int) {
@@ -1050,7 +1050,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
                break;
        }
 
-       list_for_each_entry(wdev_iter, &rdev->netdev_list, list) {
+       list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
                if (wdev_iter == wdev)
                        continue;
                if (!netif_running(wdev_iter->netdev))
@@ -1059,7 +1059,16 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
                if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
                        continue;
 
-               cfg80211_get_chan_state(rdev, wdev_iter, &ch, &chmode);
+               /*
+                * We may be holding the "wdev" mutex, but now need to lock
+                * wdev_iter. This is OK because once we get here wdev_iter
+                * is not wdev (tested above), but we need to use the nested
+                * locking for lockdep.
+                */
+               mutex_lock_nested(&wdev_iter->mtx, 1);
+               __acquire(wdev_iter->mtx);
+               cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
+               wdev_unlock(wdev_iter);
 
                switch (chmode) {
                case CHAN_MODE_UNDEFINED: