diff options
-rw-r--r-- | drivers/net/wireless/at76c50x-usb.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/cw1200/scan.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/cw1200/scan.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlegacy/common.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlegacy/common.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl1251/main.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 3 | ||||
-rw-r--r-- | include/net/mac80211.h | 39 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 9 | ||||
-rw-r--r-- | net/mac80211/scan.c | 85 | ||||
-rw-r--r-- | net/mac80211/util.c | 105 |
16 files changed, 198 insertions, 73 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index d48776e4f343..334c2ece855a 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -1955,8 +1955,9 @@ static void at76_dwork_hw_scan(struct work_struct *work) | |||
1955 | 1955 | ||
1956 | static int at76_hw_scan(struct ieee80211_hw *hw, | 1956 | static int at76_hw_scan(struct ieee80211_hw *hw, |
1957 | struct ieee80211_vif *vif, | 1957 | struct ieee80211_vif *vif, |
1958 | struct cfg80211_scan_request *req) | 1958 | struct ieee80211_scan_request *hw_req) |
1959 | { | 1959 | { |
1960 | struct cfg80211_scan_request *req = &hw_req->req; | ||
1960 | struct at76_priv *priv = hw->priv; | 1961 | struct at76_priv *priv = hw->priv; |
1961 | struct at76_req_scan scan; | 1962 | struct at76_req_scan scan; |
1962 | u8 *ssid = NULL; | 1963 | u8 *ssid = NULL; |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index a21080028c54..b8314a534972 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -3137,10 +3137,11 @@ exit: | |||
3137 | 3137 | ||
3138 | static int ath10k_hw_scan(struct ieee80211_hw *hw, | 3138 | static int ath10k_hw_scan(struct ieee80211_hw *hw, |
3139 | struct ieee80211_vif *vif, | 3139 | struct ieee80211_vif *vif, |
3140 | struct cfg80211_scan_request *req) | 3140 | struct ieee80211_scan_request *hw_req) |
3141 | { | 3141 | { |
3142 | struct ath10k *ar = hw->priv; | 3142 | struct ath10k *ar = hw->priv; |
3143 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 3143 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
3144 | struct cfg80211_scan_request *req = &hw_req->req; | ||
3144 | struct wmi_start_scan_arg arg; | 3145 | struct wmi_start_scan_arg arg; |
3145 | int ret = 0; | 3146 | int ret = 0; |
3146 | int i; | 3147 | int i; |
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index 9afcd4ce3368..b2fb6c632092 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c | |||
@@ -53,9 +53,10 @@ static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan) | |||
53 | 53 | ||
54 | int cw1200_hw_scan(struct ieee80211_hw *hw, | 54 | int cw1200_hw_scan(struct ieee80211_hw *hw, |
55 | struct ieee80211_vif *vif, | 55 | struct ieee80211_vif *vif, |
56 | struct cfg80211_scan_request *req) | 56 | struct ieee80211_scan_request *hw_req) |
57 | { | 57 | { |
58 | struct cw1200_common *priv = hw->priv; | 58 | struct cw1200_common *priv = hw->priv; |
59 | struct cfg80211_scan_request *req = &hw_req->req; | ||
59 | struct wsm_template_frame frame = { | 60 | struct wsm_template_frame frame = { |
60 | .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST, | 61 | .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST, |
61 | }; | 62 | }; |
diff --git a/drivers/net/wireless/cw1200/scan.h b/drivers/net/wireless/cw1200/scan.h index 5a8296ccfa82..cc75459e5784 100644 --- a/drivers/net/wireless/cw1200/scan.h +++ b/drivers/net/wireless/cw1200/scan.h | |||
@@ -41,7 +41,7 @@ struct cw1200_scan { | |||
41 | 41 | ||
42 | int cw1200_hw_scan(struct ieee80211_hw *hw, | 42 | int cw1200_hw_scan(struct ieee80211_hw *hw, |
43 | struct ieee80211_vif *vif, | 43 | struct ieee80211_vif *vif, |
44 | struct cfg80211_scan_request *req); | 44 | struct ieee80211_scan_request *hw_req); |
45 | void cw1200_scan_work(struct work_struct *work); | 45 | void cw1200_scan_work(struct work_struct *work); |
46 | void cw1200_scan_timeout(struct work_struct *work); | 46 | void cw1200_scan_timeout(struct work_struct *work); |
47 | void cw1200_clear_recent_scan_work(struct work_struct *work); | 47 | void cw1200_clear_recent_scan_work(struct work_struct *work); |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index ecc674627e6e..03de7467aecf 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -1572,8 +1572,9 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) | |||
1572 | 1572 | ||
1573 | int | 1573 | int |
1574 | il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1574 | il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1575 | struct cfg80211_scan_request *req) | 1575 | struct ieee80211_scan_request *hw_req) |
1576 | { | 1576 | { |
1577 | struct cfg80211_scan_request *req = &hw_req->req; | ||
1577 | struct il_priv *il = hw->priv; | 1578 | struct il_priv *il = hw->priv; |
1578 | int ret; | 1579 | int ret; |
1579 | 1580 | ||
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index ea5c0f863c4e..5b972798bdff 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h | |||
@@ -1787,7 +1787,7 @@ int il_scan_cancel(struct il_priv *il); | |||
1787 | int il_scan_cancel_timeout(struct il_priv *il, unsigned long ms); | 1787 | int il_scan_cancel_timeout(struct il_priv *il, unsigned long ms); |
1788 | void il_force_scan_end(struct il_priv *il); | 1788 | void il_force_scan_end(struct il_priv *il); |
1789 | int il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1789 | int il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1790 | struct cfg80211_scan_request *req); | 1790 | struct ieee80211_scan_request *hw_req); |
1791 | void il_internal_short_hw_scan(struct il_priv *il); | 1791 | void il_internal_short_hw_scan(struct il_priv *il); |
1792 | int il_force_reset(struct il_priv *il, bool external); | 1792 | int il_force_reset(struct il_priv *il, bool external); |
1793 | u16 il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame, | 1793 | u16 il_fill_probe_req(struct il_priv *il, struct ieee80211_mgmt *frame, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 29af7b51e370..afb98f4fdaf3 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1495,9 +1495,10 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | |||
1495 | 1495 | ||
1496 | static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | 1496 | static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, |
1497 | struct ieee80211_vif *vif, | 1497 | struct ieee80211_vif *vif, |
1498 | struct cfg80211_scan_request *req) | 1498 | struct ieee80211_scan_request *hw_req) |
1499 | { | 1499 | { |
1500 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1500 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1501 | struct cfg80211_scan_request *req = &hw_req->req; | ||
1501 | int ret; | 1502 | int ret; |
1502 | 1503 | ||
1503 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1504 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7215f5980186..4dc2e05f49ce 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -1537,9 +1537,10 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, | |||
1537 | 1537 | ||
1538 | static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | 1538 | static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, |
1539 | struct ieee80211_vif *vif, | 1539 | struct ieee80211_vif *vif, |
1540 | struct cfg80211_scan_request *req) | 1540 | struct ieee80211_scan_request *hw_req) |
1541 | { | 1541 | { |
1542 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1542 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1543 | struct cfg80211_scan_request *req = &hw_req->req; | ||
1543 | int ret; | 1544 | int ret; |
1544 | 1545 | ||
1545 | if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS) | 1546 | if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS) |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 06a0722164da..eba51460a5de 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1736,9 +1736,10 @@ static void hw_scan_work(struct work_struct *work) | |||
1736 | 1736 | ||
1737 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | 1737 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, |
1738 | struct ieee80211_vif *vif, | 1738 | struct ieee80211_vif *vif, |
1739 | struct cfg80211_scan_request *req) | 1739 | struct ieee80211_scan_request *hw_req) |
1740 | { | 1740 | { |
1741 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1741 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1742 | struct cfg80211_scan_request *req = &hw_req->req; | ||
1742 | 1743 | ||
1743 | mutex_lock(&hwsim->mutex); | 1744 | mutex_lock(&hwsim->mutex); |
1744 | if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { | 1745 | if (WARN_ON(hwsim->tmp_chan || hwsim->hw_scan_request)) { |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 4e782f18ae34..38234851457e 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -991,8 +991,9 @@ out: | |||
991 | 991 | ||
992 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | 992 | static int wl1251_op_hw_scan(struct ieee80211_hw *hw, |
993 | struct ieee80211_vif *vif, | 993 | struct ieee80211_vif *vif, |
994 | struct cfg80211_scan_request *req) | 994 | struct ieee80211_scan_request *hw_req) |
995 | { | 995 | { |
996 | struct cfg80211_scan_request *req = &hw_req->req; | ||
996 | struct wl1251 *wl = hw->priv; | 997 | struct wl1251 *wl = hw->priv; |
997 | struct sk_buff *skb; | 998 | struct sk_buff *skb; |
998 | size_t ssid_len = 0; | 999 | size_t ssid_len = 0; |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 3d6028e62750..e5ffb8b91dd4 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -3540,8 +3540,9 @@ out: | |||
3540 | 3540 | ||
3541 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | 3541 | static int wl1271_op_hw_scan(struct ieee80211_hw *hw, |
3542 | struct ieee80211_vif *vif, | 3542 | struct ieee80211_vif *vif, |
3543 | struct cfg80211_scan_request *req) | 3543 | struct ieee80211_scan_request *hw_req) |
3544 | { | 3544 | { |
3545 | struct cfg80211_scan_request *req = &hw_req->req; | ||
3545 | struct wl1271 *wl = hw->priv; | 3546 | struct wl1271 *wl = hw->priv; |
3546 | int ret; | 3547 | int ret; |
3547 | u8 *ssid = NULL; | 3548 | u8 *ssid = NULL; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 18c2bdbaf988..9536ee3e22a9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -768,6 +768,26 @@ struct ieee80211_sched_scan_ies { | |||
768 | size_t len[IEEE80211_NUM_BANDS]; | 768 | size_t len[IEEE80211_NUM_BANDS]; |
769 | }; | 769 | }; |
770 | 770 | ||
771 | /** | ||
772 | * struct ieee80211_scan_ies - descriptors for different blocks of IEs | ||
773 | * | ||
774 | * This structure is used to point to different blocks of IEs in HW scan. | ||
775 | * These blocks contain the IEs passed by userspace and the ones generated | ||
776 | * by mac80211. | ||
777 | * | ||
778 | * @ies: pointers to band specific IEs. | ||
779 | * @len: lengths of band_specific IEs. | ||
780 | * @common_ies: IEs for all bands (especially vendor specific ones) | ||
781 | * @common_ie_len: length of the common_ies | ||
782 | */ | ||
783 | struct ieee80211_scan_ies { | ||
784 | const u8 *ies[IEEE80211_NUM_BANDS]; | ||
785 | size_t len[IEEE80211_NUM_BANDS]; | ||
786 | const u8 *common_ies; | ||
787 | size_t common_ie_len; | ||
788 | }; | ||
789 | |||
790 | |||
771 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) | 791 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) |
772 | { | 792 | { |
773 | return (struct ieee80211_tx_info *)skb->cb; | 793 | return (struct ieee80211_tx_info *)skb->cb; |
@@ -1606,6 +1626,9 @@ struct ieee80211_tx_control { | |||
1606 | * on single-channel hardware. It can also be used as an | 1626 | * on single-channel hardware. It can also be used as an |
1607 | * optimization in certain channel switch cases with | 1627 | * optimization in certain channel switch cases with |
1608 | * multi-channel. | 1628 | * multi-channel. |
1629 | * | ||
1630 | * @IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands | ||
1631 | * in one command, mac80211 doesn't have to run separate scans per band. | ||
1609 | */ | 1632 | */ |
1610 | enum ieee80211_hw_flags { | 1633 | enum ieee80211_hw_flags { |
1611 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1634 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1638,6 +1661,7 @@ enum ieee80211_hw_flags { | |||
1638 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, | 1661 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES = 1<<27, |
1639 | IEEE80211_HW_CHANCTX_STA_CSA = 1<<28, | 1662 | IEEE80211_HW_CHANCTX_STA_CSA = 1<<28, |
1640 | IEEE80211_HW_CHANGE_RUNNING_CHANCTX = 1<<29, | 1663 | IEEE80211_HW_CHANGE_RUNNING_CHANCTX = 1<<29, |
1664 | IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS = 1<<30, | ||
1641 | }; | 1665 | }; |
1642 | 1666 | ||
1643 | /** | 1667 | /** |
@@ -1764,6 +1788,19 @@ struct ieee80211_hw { | |||
1764 | }; | 1788 | }; |
1765 | 1789 | ||
1766 | /** | 1790 | /** |
1791 | * struct ieee80211_scan_request - hw scan request | ||
1792 | * | ||
1793 | * @ies: pointers different parts of IEs (in req.ie) | ||
1794 | * @req: cfg80211 request. | ||
1795 | */ | ||
1796 | struct ieee80211_scan_request { | ||
1797 | struct ieee80211_scan_ies ies; | ||
1798 | |||
1799 | /* Keep last */ | ||
1800 | struct cfg80211_scan_request req; | ||
1801 | }; | ||
1802 | |||
1803 | /** | ||
1767 | * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy | 1804 | * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy |
1768 | * | 1805 | * |
1769 | * @wiphy: the &struct wiphy which we want to query | 1806 | * @wiphy: the &struct wiphy which we want to query |
@@ -2874,7 +2911,7 @@ struct ieee80211_ops { | |||
2874 | void (*set_default_unicast_key)(struct ieee80211_hw *hw, | 2911 | void (*set_default_unicast_key)(struct ieee80211_hw *hw, |
2875 | struct ieee80211_vif *vif, int idx); | 2912 | struct ieee80211_vif *vif, int idx); |
2876 | int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2913 | int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2877 | struct cfg80211_scan_request *req); | 2914 | struct ieee80211_scan_request *req); |
2878 | void (*cancel_hw_scan)(struct ieee80211_hw *hw, | 2915 | void (*cancel_hw_scan)(struct ieee80211_hw *hw, |
2879 | struct ieee80211_vif *vif); | 2916 | struct ieee80211_vif *vif); |
2880 | int (*sched_scan_start)(struct ieee80211_hw *hw, | 2917 | int (*sched_scan_start)(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 2265bd7a44ba..faa0d90f6e80 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -314,7 +314,7 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
314 | 314 | ||
315 | static inline int drv_hw_scan(struct ieee80211_local *local, | 315 | static inline int drv_hw_scan(struct ieee80211_local *local, |
316 | struct ieee80211_sub_if_data *sdata, | 316 | struct ieee80211_sub_if_data *sdata, |
317 | struct cfg80211_scan_request *req) | 317 | struct ieee80211_scan_request *req) |
318 | { | 318 | { |
319 | int ret; | 319 | int ret; |
320 | 320 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6c8089429892..f88bd1659cde 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1152,7 +1152,8 @@ struct ieee80211_local { | |||
1152 | unsigned long scanning; | 1152 | unsigned long scanning; |
1153 | struct cfg80211_ssid scan_ssid; | 1153 | struct cfg80211_ssid scan_ssid; |
1154 | struct cfg80211_scan_request *int_scan_req; | 1154 | struct cfg80211_scan_request *int_scan_req; |
1155 | struct cfg80211_scan_request *scan_req, *hw_scan_req; | 1155 | struct cfg80211_scan_request *scan_req; |
1156 | struct ieee80211_scan_request *hw_scan_req; | ||
1156 | struct cfg80211_chan_def scan_chandef; | 1157 | struct cfg80211_chan_def scan_chandef; |
1157 | enum ieee80211_band hw_scan_band; | 1158 | enum ieee80211_band hw_scan_band; |
1158 | int scan_channel_idx; | 1159 | int scan_channel_idx; |
@@ -1756,8 +1757,10 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1756 | const u8 *bssid, u16 stype, u16 reason, | 1757 | const u8 *bssid, u16 stype, u16 reason, |
1757 | bool send_frame, u8 *frame_buf); | 1758 | bool send_frame, u8 *frame_buf); |
1758 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1759 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1759 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1760 | size_t buffer_len, |
1760 | enum ieee80211_band band, u32 rate_mask, | 1761 | struct ieee80211_scan_ies *ie_desc, |
1762 | const u8 *ie, size_t ie_len, | ||
1763 | u8 bands_used, u32 *rate_masks, | ||
1761 | struct cfg80211_chan_def *chandef); | 1764 | struct cfg80211_chan_def *chandef); |
1762 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1765 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1763 | u8 *dst, u32 ratemask, | 1766 | u8 *dst, u32 ratemask, |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f40661eb75b5..116959e070d0 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -235,38 +235,51 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
235 | { | 235 | { |
236 | struct cfg80211_scan_request *req = local->scan_req; | 236 | struct cfg80211_scan_request *req = local->scan_req; |
237 | struct cfg80211_chan_def chandef; | 237 | struct cfg80211_chan_def chandef; |
238 | enum ieee80211_band band; | 238 | u8 bands_used = 0; |
239 | int i, ielen, n_chans; | 239 | int i, ielen, n_chans; |
240 | 240 | ||
241 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) | 241 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) |
242 | return false; | 242 | return false; |
243 | 243 | ||
244 | do { | 244 | if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) { |
245 | if (local->hw_scan_band == IEEE80211_NUM_BANDS) | ||
246 | return false; | ||
247 | |||
248 | band = local->hw_scan_band; | ||
249 | n_chans = 0; | ||
250 | for (i = 0; i < req->n_channels; i++) { | 245 | for (i = 0; i < req->n_channels; i++) { |
251 | if (req->channels[i]->band == band) { | 246 | local->hw_scan_req->req.channels[i] = req->channels[i]; |
252 | local->hw_scan_req->channels[n_chans] = | 247 | bands_used |= BIT(req->channels[i]->band); |
248 | } | ||
249 | |||
250 | n_chans = req->n_channels; | ||
251 | } else { | ||
252 | do { | ||
253 | if (local->hw_scan_band == IEEE80211_NUM_BANDS) | ||
254 | return false; | ||
255 | |||
256 | n_chans = 0; | ||
257 | |||
258 | for (i = 0; i < req->n_channels; i++) { | ||
259 | if (req->channels[i]->band != | ||
260 | local->hw_scan_band) | ||
261 | continue; | ||
262 | local->hw_scan_req->req.channels[n_chans] = | ||
253 | req->channels[i]; | 263 | req->channels[i]; |
254 | n_chans++; | 264 | n_chans++; |
265 | bands_used |= BIT(req->channels[i]->band); | ||
255 | } | 266 | } |
256 | } | ||
257 | 267 | ||
258 | local->hw_scan_band++; | 268 | local->hw_scan_band++; |
259 | } while (!n_chans); | 269 | } while (!n_chans); |
270 | } | ||
260 | 271 | ||
261 | local->hw_scan_req->n_channels = n_chans; | 272 | local->hw_scan_req->req.n_channels = n_chans; |
262 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | 273 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); |
263 | 274 | ||
264 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, | 275 | ielen = ieee80211_build_preq_ies(local, |
276 | (u8 *)local->hw_scan_req->req.ie, | ||
265 | local->hw_scan_ies_bufsize, | 277 | local->hw_scan_ies_bufsize, |
266 | req->ie, req->ie_len, band, | 278 | &local->hw_scan_req->ies, |
267 | req->rates[band], &chandef); | 279 | req->ie, req->ie_len, |
268 | local->hw_scan_req->ie_len = ielen; | 280 | bands_used, req->rates, &chandef); |
269 | local->hw_scan_req->no_cck = req->no_cck; | 281 | local->hw_scan_req->req.ie_len = ielen; |
282 | local->hw_scan_req->req.no_cck = req->no_cck; | ||
270 | 283 | ||
271 | return true; | 284 | return true; |
272 | } | 285 | } |
@@ -291,7 +304,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
291 | if (WARN_ON(!local->scan_req)) | 304 | if (WARN_ON(!local->scan_req)) |
292 | return; | 305 | return; |
293 | 306 | ||
294 | if (hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 307 | if (hw_scan && !aborted && |
308 | !(local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) && | ||
309 | ieee80211_prep_hw_scan(local)) { | ||
295 | int rc; | 310 | int rc; |
296 | 311 | ||
297 | rc = drv_hw_scan(local, | 312 | rc = drv_hw_scan(local, |
@@ -473,6 +488,21 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
473 | u8 *ies; | 488 | u8 *ies; |
474 | 489 | ||
475 | local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len; | 490 | local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len; |
491 | |||
492 | if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) { | ||
493 | int i, n_bands = 0; | ||
494 | u8 bands_counted = 0; | ||
495 | |||
496 | for (i = 0; i < req->n_channels; i++) { | ||
497 | if (bands_counted & BIT(req->channels[i]->band)) | ||
498 | continue; | ||
499 | bands_counted |= BIT(req->channels[i]->band); | ||
500 | n_bands++; | ||
501 | } | ||
502 | |||
503 | local->hw_scan_ies_bufsize *= n_bands; | ||
504 | } | ||
505 | |||
476 | local->hw_scan_req = kmalloc( | 506 | local->hw_scan_req = kmalloc( |
477 | sizeof(*local->hw_scan_req) + | 507 | sizeof(*local->hw_scan_req) + |
478 | req->n_channels * sizeof(req->channels[0]) + | 508 | req->n_channels * sizeof(req->channels[0]) + |
@@ -480,13 +510,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
480 | if (!local->hw_scan_req) | 510 | if (!local->hw_scan_req) |
481 | return -ENOMEM; | 511 | return -ENOMEM; |
482 | 512 | ||
483 | local->hw_scan_req->ssids = req->ssids; | 513 | local->hw_scan_req->req.ssids = req->ssids; |
484 | local->hw_scan_req->n_ssids = req->n_ssids; | 514 | local->hw_scan_req->req.n_ssids = req->n_ssids; |
485 | ies = (u8 *)local->hw_scan_req + | 515 | ies = (u8 *)local->hw_scan_req + |
486 | sizeof(*local->hw_scan_req) + | 516 | sizeof(*local->hw_scan_req) + |
487 | req->n_channels * sizeof(req->channels[0]); | 517 | req->n_channels * sizeof(req->channels[0]); |
488 | local->hw_scan_req->ie = ies; | 518 | local->hw_scan_req->req.ie = ies; |
489 | local->hw_scan_req->flags = req->flags; | 519 | local->hw_scan_req->req.flags = req->flags; |
490 | 520 | ||
491 | local->hw_scan_band = 0; | 521 | local->hw_scan_band = 0; |
492 | 522 | ||
@@ -976,6 +1006,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
976 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; | 1006 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; |
977 | struct cfg80211_chan_def chandef; | 1007 | struct cfg80211_chan_def chandef; |
978 | int ret, i, iebufsz; | 1008 | int ret, i, iebufsz; |
1009 | struct ieee80211_scan_ies dummy_ie_desc; | ||
979 | 1010 | ||
980 | iebufsz = local->scan_ies_len + req->ie_len; | 1011 | iebufsz = local->scan_ies_len + req->ie_len; |
981 | 1012 | ||
@@ -985,6 +1016,8 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
985 | return -ENOTSUPP; | 1016 | return -ENOTSUPP; |
986 | 1017 | ||
987 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1018 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1019 | u32 rate_masks[IEEE80211_NUM_BANDS] = {}; | ||
1020 | |||
988 | if (!local->hw.wiphy->bands[i]) | 1021 | if (!local->hw.wiphy->bands[i]) |
989 | continue; | 1022 | continue; |
990 | 1023 | ||
@@ -995,11 +1028,13 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
995 | } | 1028 | } |
996 | 1029 | ||
997 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | 1030 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); |
1031 | rate_masks[i] = (u32) -1; | ||
998 | 1032 | ||
999 | sched_scan_ies.len[i] = | 1033 | sched_scan_ies.len[i] = |
1000 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], | 1034 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], |
1001 | iebufsz, req->ie, req->ie_len, | 1035 | iebufsz, &dummy_ie_desc, |
1002 | i, (u32) -1, &chandef); | 1036 | req->ie, req->ie_len, BIT(i), |
1037 | rate_masks, &chandef); | ||
1003 | } | 1038 | } |
1004 | 1039 | ||
1005 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1040 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 42d448d765b4..e31458201278 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1219,14 +1219,17 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1219 | } | 1219 | } |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1222 | static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, |
1223 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1223 | u8 *buffer, size_t buffer_len, |
1224 | enum ieee80211_band band, u32 rate_mask, | 1224 | const u8 *ie, size_t ie_len, |
1225 | struct cfg80211_chan_def *chandef) | 1225 | enum ieee80211_band band, |
1226 | u32 rate_mask, | ||
1227 | struct cfg80211_chan_def *chandef, | ||
1228 | size_t *offset) | ||
1226 | { | 1229 | { |
1227 | struct ieee80211_supported_band *sband; | 1230 | struct ieee80211_supported_band *sband; |
1228 | u8 *pos = buffer, *end = buffer + buffer_len; | 1231 | u8 *pos = buffer, *end = buffer + buffer_len; |
1229 | size_t offset = 0, noffset; | 1232 | size_t noffset; |
1230 | int supp_rates_len, i; | 1233 | int supp_rates_len, i; |
1231 | u8 rates[32]; | 1234 | u8 rates[32]; |
1232 | int num_rates; | 1235 | int num_rates; |
@@ -1234,6 +1237,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1234 | int shift; | 1237 | int shift; |
1235 | u32 rate_flags; | 1238 | u32 rate_flags; |
1236 | 1239 | ||
1240 | *offset = 0; | ||
1241 | |||
1237 | sband = local->hw.wiphy->bands[band]; | 1242 | sband = local->hw.wiphy->bands[band]; |
1238 | if (WARN_ON_ONCE(!sband)) | 1243 | if (WARN_ON_ONCE(!sband)) |
1239 | return 0; | 1244 | return 0; |
@@ -1272,12 +1277,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1272 | noffset = ieee80211_ie_split(ie, ie_len, | 1277 | noffset = ieee80211_ie_split(ie, ie_len, |
1273 | before_extrates, | 1278 | before_extrates, |
1274 | ARRAY_SIZE(before_extrates), | 1279 | ARRAY_SIZE(before_extrates), |
1275 | offset); | 1280 | *offset); |
1276 | if (end - pos < noffset - offset) | 1281 | if (end - pos < noffset - *offset) |
1277 | goto out_err; | 1282 | goto out_err; |
1278 | memcpy(pos, ie + offset, noffset - offset); | 1283 | memcpy(pos, ie + *offset, noffset - *offset); |
1279 | pos += noffset - offset; | 1284 | pos += noffset - *offset; |
1280 | offset = noffset; | 1285 | *offset = noffset; |
1281 | } | 1286 | } |
1282 | 1287 | ||
1283 | ext_rates_len = num_rates - supp_rates_len; | 1288 | ext_rates_len = num_rates - supp_rates_len; |
@@ -1311,12 +1316,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1311 | }; | 1316 | }; |
1312 | noffset = ieee80211_ie_split(ie, ie_len, | 1317 | noffset = ieee80211_ie_split(ie, ie_len, |
1313 | before_ht, ARRAY_SIZE(before_ht), | 1318 | before_ht, ARRAY_SIZE(before_ht), |
1314 | offset); | 1319 | *offset); |
1315 | if (end - pos < noffset - offset) | 1320 | if (end - pos < noffset - *offset) |
1316 | goto out_err; | 1321 | goto out_err; |
1317 | memcpy(pos, ie + offset, noffset - offset); | 1322 | memcpy(pos, ie + *offset, noffset - *offset); |
1318 | pos += noffset - offset; | 1323 | pos += noffset - *offset; |
1319 | offset = noffset; | 1324 | *offset = noffset; |
1320 | } | 1325 | } |
1321 | 1326 | ||
1322 | if (sband->ht_cap.ht_supported) { | 1327 | if (sband->ht_cap.ht_supported) { |
@@ -1351,12 +1356,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1351 | }; | 1356 | }; |
1352 | noffset = ieee80211_ie_split(ie, ie_len, | 1357 | noffset = ieee80211_ie_split(ie, ie_len, |
1353 | before_vht, ARRAY_SIZE(before_vht), | 1358 | before_vht, ARRAY_SIZE(before_vht), |
1354 | offset); | 1359 | *offset); |
1355 | if (end - pos < noffset - offset) | 1360 | if (end - pos < noffset - *offset) |
1356 | goto out_err; | 1361 | goto out_err; |
1357 | memcpy(pos, ie + offset, noffset - offset); | 1362 | memcpy(pos, ie + *offset, noffset - *offset); |
1358 | pos += noffset - offset; | 1363 | pos += noffset - *offset; |
1359 | offset = noffset; | 1364 | *offset = noffset; |
1360 | } | 1365 | } |
1361 | 1366 | ||
1362 | if (sband->vht_cap.vht_supported) { | 1367 | if (sband->vht_cap.vht_supported) { |
@@ -1366,21 +1371,54 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1366 | sband->vht_cap.cap); | 1371 | sband->vht_cap.cap); |
1367 | } | 1372 | } |
1368 | 1373 | ||
1369 | /* add any remaining custom IEs */ | ||
1370 | if (ie && ie_len) { | ||
1371 | noffset = ie_len; | ||
1372 | if (end - pos < noffset - offset) | ||
1373 | goto out_err; | ||
1374 | memcpy(pos, ie + offset, noffset - offset); | ||
1375 | pos += noffset - offset; | ||
1376 | } | ||
1377 | |||
1378 | return pos - buffer; | 1374 | return pos - buffer; |
1379 | out_err: | 1375 | out_err: |
1380 | WARN_ONCE(1, "not enough space for preq IEs\n"); | 1376 | WARN_ONCE(1, "not enough space for preq IEs\n"); |
1381 | return pos - buffer; | 1377 | return pos - buffer; |
1382 | } | 1378 | } |
1383 | 1379 | ||
1380 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | ||
1381 | size_t buffer_len, | ||
1382 | struct ieee80211_scan_ies *ie_desc, | ||
1383 | const u8 *ie, size_t ie_len, | ||
1384 | u8 bands_used, u32 *rate_masks, | ||
1385 | struct cfg80211_chan_def *chandef) | ||
1386 | { | ||
1387 | size_t pos = 0, old_pos = 0, custom_ie_offset = 0; | ||
1388 | int i; | ||
1389 | |||
1390 | memset(ie_desc, 0, sizeof(*ie_desc)); | ||
1391 | |||
1392 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
1393 | if (bands_used & BIT(i)) { | ||
1394 | pos += ieee80211_build_preq_ies_band(local, | ||
1395 | buffer + pos, | ||
1396 | buffer_len - pos, | ||
1397 | ie, ie_len, i, | ||
1398 | rate_masks[i], | ||
1399 | chandef, | ||
1400 | &custom_ie_offset); | ||
1401 | ie_desc->ies[i] = buffer + old_pos; | ||
1402 | ie_desc->len[i] = pos - old_pos; | ||
1403 | old_pos = pos; | ||
1404 | } | ||
1405 | } | ||
1406 | |||
1407 | /* add any remaining custom IEs */ | ||
1408 | if (ie && ie_len) { | ||
1409 | if (WARN_ONCE(buffer_len - pos < ie_len - custom_ie_offset, | ||
1410 | "not enough space for preq custom IEs\n")) | ||
1411 | return pos; | ||
1412 | memcpy(buffer + pos, ie + custom_ie_offset, | ||
1413 | ie_len - custom_ie_offset); | ||
1414 | ie_desc->common_ies = buffer + pos; | ||
1415 | ie_desc->common_ie_len = ie_len - custom_ie_offset; | ||
1416 | pos += ie_len - custom_ie_offset; | ||
1417 | } | ||
1418 | |||
1419 | return pos; | ||
1420 | }; | ||
1421 | |||
1384 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1422 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1385 | u8 *dst, u32 ratemask, | 1423 | u8 *dst, u32 ratemask, |
1386 | struct ieee80211_channel *chan, | 1424 | struct ieee80211_channel *chan, |
@@ -1393,6 +1431,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1393 | struct sk_buff *skb; | 1431 | struct sk_buff *skb; |
1394 | struct ieee80211_mgmt *mgmt; | 1432 | struct ieee80211_mgmt *mgmt; |
1395 | int ies_len; | 1433 | int ies_len; |
1434 | u32 rate_masks[IEEE80211_NUM_BANDS] = {}; | ||
1435 | struct ieee80211_scan_ies dummy_ie_desc; | ||
1396 | 1436 | ||
1397 | /* | 1437 | /* |
1398 | * Do not send DS Channel parameter for directed probe requests | 1438 | * Do not send DS Channel parameter for directed probe requests |
@@ -1410,10 +1450,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1410 | if (!skb) | 1450 | if (!skb) |
1411 | return NULL; | 1451 | return NULL; |
1412 | 1452 | ||
1453 | rate_masks[chan->band] = ratemask; | ||
1413 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | 1454 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), |
1414 | skb_tailroom(skb), | 1455 | skb_tailroom(skb), &dummy_ie_desc, |
1415 | ie, ie_len, chan->band, | 1456 | ie, ie_len, BIT(chan->band), |
1416 | ratemask, &chandef); | 1457 | rate_masks, &chandef); |
1417 | skb_put(skb, ies_len); | 1458 | skb_put(skb, ies_len); |
1418 | 1459 | ||
1419 | if (dst) { | 1460 | if (dst) { |