diff options
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx/main.c')
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/main.c | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 3c2522b..96a9584 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -568,23 +568,59 @@ out: return ret; } -static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *mac_addr) +static void wcn36xx_hw_scan_worker(struct work_struct *work) { - struct wcn36xx *wcn = hw->priv; + struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work); + struct cfg80211_scan_request *req = wcn->scan_req; + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; + struct cfg80211_scan_info scan_info = {}; + int i; + + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels); + + for (i = 0; i < req->n_channels; i++) + channels[i] = req->channels[i]->hw_value; + + wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels); wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); - wcn36xx_smd_start_scan(wcn); + for (i = 0; i < req->n_channels; i++) { + wcn->scan_freq = req->channels[i]->center_freq; + wcn->scan_band = req->channels[i]->band; + + wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value); + msleep(30); + wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value); + + wcn->scan_freq = 0; + } + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); + + scan_info.aborted = false; + ieee80211_scan_completed(wcn->hw, &scan_info); + + mutex_lock(&wcn->scan_lock); + wcn->scan_req = NULL; + mutex_unlock(&wcn->scan_lock); } -static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int wcn36xx_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) { struct wcn36xx *wcn = hw->priv; - wcn36xx_smd_end_scan(wcn); - wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); + mutex_lock(&wcn->scan_lock); + if (wcn->scan_req) { + mutex_unlock(&wcn->scan_lock); + return -EBUSY; + } + wcn->scan_req = &hw_req->req; + mutex_unlock(&wcn->scan_lock); + + schedule_work(&wcn->scan_work); + + return 0; } static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, @@ -997,8 +1033,7 @@ static const struct ieee80211_ops wcn36xx_ops = { .configure_filter = wcn36xx_configure_filter, .tx = wcn36xx_tx, .set_key = wcn36xx_set_key, - .sw_scan_start = wcn36xx_sw_scan_start, - .sw_scan_complete = wcn36xx_sw_scan_complete, + .hw_scan = wcn36xx_hw_scan, .bss_info_changed = wcn36xx_bss_info_changed, .set_rts_threshold = wcn36xx_set_rts_threshold, .sta_add = wcn36xx_sta_add, @@ -1023,6 +1058,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) ieee80211_hw_set(wcn->hw, SUPPORTS_PS); ieee80211_hw_set(wcn->hw, SIGNAL_DBM); ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); + ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS); wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | @@ -1032,6 +1068,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz; wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; + wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; + wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN; + wcn->hw->wiphy->cipher_suites = cipher_suites; wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); @@ -1152,6 +1191,9 @@ static int wcn36xx_probe(struct platform_device *pdev) wcn->hw = hw; wcn->dev = &pdev->dev; mutex_init(&wcn->hal_mutex); + mutex_init(&wcn->scan_lock); + + INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker); wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process); if (IS_ERR(wcn->smd_channel)) { |