From 1c055e55a242a33e574e48be530e06770a210dcd Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 19 Feb 2024 03:26:26 +0000 Subject: [PATCH] add r8169 read mac form eeprom --- kernel/drivers/net/wireless/ath/wcn36xx/main.c | 316 ++++++++++++++++++++++++++++++++++------------------ 1 files changed, 204 insertions(+), 112 deletions(-) diff --git a/kernel/drivers/net/wireless/ath/wcn36xx/main.c b/kernel/drivers/net/wireless/ath/wcn36xx/main.c index eb5d08b..37e6e49 100644 --- a/kernel/drivers/net/wireless/ath/wcn36xx/main.c +++ b/kernel/drivers/net/wireless/ath/wcn36xx/main.c @@ -39,10 +39,10 @@ .max_power = 25, \ } -#define CHAN5G(_freq, _idx) { \ +#define CHAN5G(_freq, _idx, _phy_val) { \ .band = NL80211_BAND_5GHZ, \ .center_freq = (_freq), \ - .hw_value = (_idx), \ + .hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \ .max_power = 25, \ } @@ -67,29 +67,29 @@ }; static struct ieee80211_channel wcn_5ghz_channels[] = { - CHAN5G(5180, 36), - CHAN5G(5200, 40), - CHAN5G(5220, 44), - CHAN5G(5240, 48), - CHAN5G(5260, 52), - CHAN5G(5280, 56), - CHAN5G(5300, 60), - CHAN5G(5320, 64), - CHAN5G(5500, 100), - CHAN5G(5520, 104), - CHAN5G(5540, 108), - CHAN5G(5560, 112), - CHAN5G(5580, 116), - CHAN5G(5600, 120), - CHAN5G(5620, 124), - CHAN5G(5640, 128), - CHAN5G(5660, 132), - CHAN5G(5700, 140), - CHAN5G(5745, 149), - CHAN5G(5765, 153), - CHAN5G(5785, 157), - CHAN5G(5805, 161), - CHAN5G(5825, 165) + CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW), + CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW), + CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH), + CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH), + CHAN5G(5825, 165, 0) }; #define RATE(_bitrate, _hw_rate, _flags) { \ @@ -347,8 +347,6 @@ wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n"); - cancel_work_sync(&wcn->scan_work); - mutex_lock(&wcn->scan_lock); if (wcn->scan_req) { struct cfg80211_scan_info scan_info = { @@ -369,11 +367,37 @@ wcn36xx_dxe_free_ctl_blks(wcn); } +static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable) +{ + struct ieee80211_vif *vif = NULL; + struct wcn36xx_vif *tmp; + + list_for_each_entry(tmp, &wcn->vif_list, list) { + vif = wcn36xx_priv_to_vif(tmp); + if (enable && !wcn->sw_scan) { + if (vif->bss_conf.ps) /* ps allowed ? */ + wcn36xx_pmc_enter_bmps_state(wcn, vif); + } else { + wcn36xx_pmc_exit_bmps_state(wcn, vif); + } + } +} + +static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch) +{ + struct ieee80211_vif *vif = NULL; + struct wcn36xx_vif *tmp; + + list_for_each_entry(tmp, &wcn->vif_list, list) { + vif = wcn36xx_priv_to_vif(tmp); + wcn36xx_smd_switch_channel(wcn, vif, ch); + } +} + static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed) { struct wcn36xx *wcn = hw->priv; - struct ieee80211_vif *vif = NULL; - struct wcn36xx_vif *tmp; + int ret; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed); @@ -383,23 +407,44 @@ int ch = WCN36XX_HW_CHANNEL(wcn); wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n", ch); - list_for_each_entry(tmp, &wcn->vif_list, list) { - vif = wcn36xx_priv_to_vif(tmp); - wcn36xx_smd_switch_channel(wcn, vif, ch); + + if (wcn->sw_scan_opchannel == ch && wcn->sw_scan_channel) { + /* If channel is the initial operating channel, we may + * want to receive/transmit regular data packets, then + * simply stop the scan session and exit PS mode. + */ + if (wcn->sw_scan_channel) + wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel); + if (wcn->sw_scan_init) { + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, + wcn->sw_scan_vif); + } + } else if (wcn->sw_scan) { + /* A scan is ongoing, do not change the operating + * channel, but start a scan session on the channel. + */ + if (wcn->sw_scan_channel) + wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel); + if (!wcn->sw_scan_init) { + /* This can fail if we are unable to notify the + * operating channel. + */ + ret = wcn36xx_smd_init_scan(wcn, + HAL_SYS_MODE_SCAN, + wcn->sw_scan_vif); + if (ret) { + mutex_unlock(&wcn->conf_mutex); + return -EIO; + } + } + wcn36xx_smd_start_scan(wcn, ch); + } else { + wcn36xx_change_opchannel(wcn, ch); } } - if (changed & IEEE80211_CONF_CHANGE_PS) { - list_for_each_entry(tmp, &wcn->vif_list, list) { - vif = wcn36xx_priv_to_vif(tmp); - if (hw->conf.flags & IEEE80211_CONF_PS) { - if (vif->bss_conf.ps) /* ps allowed ? */ - wcn36xx_pmc_enter_bmps_state(wcn, vif); - } else { - wcn36xx_pmc_exit_bmps_state(wcn, vif); - } - } - } + if (changed & IEEE80211_CONF_CHANGE_PS) + wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS); mutex_unlock(&wcn->conf_mutex); @@ -538,12 +583,14 @@ if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) { sta_priv->is_data_encrypted = true; /* Reconfigure bss with encrypt_type */ - if (NL80211_IFTYPE_STATION == vif->type) + if (NL80211_IFTYPE_STATION == vif->type) { wcn36xx_smd_config_bss(wcn, vif, sta, sta->addr, true); + wcn36xx_smd_config_sta(wcn, vif, sta); + } wcn36xx_smd_set_stakey(wcn, vif_priv->encrypt_type, @@ -605,55 +652,26 @@ return ret; } -static void wcn36xx_hw_scan_worker(struct work_struct *work) -{ - 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 = {}; - bool aborted = false; - 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); - for (i = 0; i < req->n_channels; i++) { - mutex_lock(&wcn->scan_lock); - aborted = wcn->scan_aborted; - mutex_unlock(&wcn->scan_lock); - - if (aborted) - break; - - 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 = aborted; - ieee80211_scan_completed(wcn->hw, &scan_info); - - mutex_lock(&wcn->scan_lock); - wcn->scan_req = NULL; - mutex_unlock(&wcn->scan_lock); -} - static int wcn36xx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) { struct wcn36xx *wcn = hw->priv; + int i; + + if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) { + /* fallback to mac80211 software scan */ + return 1; + } + + /* For unknown reason, the hardware offloaded scan only works with + * 2.4Ghz channels, fallback to software scan in other cases. + */ + for (i = 0; i < hw_req->req.n_channels; i++) { + if (hw_req->req.channels[i]->band != NL80211_BAND_2GHZ) + return 1; + } + mutex_lock(&wcn->scan_lock); if (wcn->scan_req) { mutex_unlock(&wcn->scan_lock); @@ -664,12 +682,6 @@ wcn->scan_req = &hw_req->req; mutex_unlock(&wcn->scan_lock); - - if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) { - /* legacy manual/sw scan */ - schedule_work(&wcn->scan_work); - return 0; - } return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req); } @@ -687,14 +699,39 @@ /* ieee80211_scan_completed will be called on FW scan * indication */ wcn36xx_smd_stop_hw_scan(wcn); - } else { - struct cfg80211_scan_info scan_info = { - .aborted = true, - }; - - cancel_work_sync(&wcn->scan_work); - ieee80211_scan_completed(wcn->hw, &scan_info); } +} + +static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) +{ + struct wcn36xx *wcn = hw->priv; + struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif); + + wcn->sw_scan = true; + wcn->sw_scan_vif = vif; + wcn->sw_scan_channel = 0; + if (vif_priv->sta_assoc) + wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn); + else + wcn->sw_scan_opchannel = 0; +} + +static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct wcn36xx *wcn = hw->priv; + + /* ensure that any scan session is finished */ + if (wcn->sw_scan_channel) + wcn36xx_smd_end_scan(wcn, wcn->sw_scan_channel); + if (wcn->sw_scan_init) { + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, + wcn->sw_scan_vif); + } + wcn->sw_scan = false; + wcn->sw_scan_opchannel = 0; } static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, @@ -736,7 +773,16 @@ sta->ht_cap.mcs.rx_mask, sizeof(sta->ht_cap.mcs.rx_mask)); } + + if (sta->vht_cap.vht_supported) { + sta_priv->supported_rates.op_rate_mode = STA_11ac; + sta_priv->supported_rates.vht_rx_mcs_map = + sta->vht_cap.vht_mcs.rx_mcs_map; + sta_priv->supported_rates.vht_tx_mcs_map = + sta->vht_cap.vht_mcs.tx_mcs_map; + } } + void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates) { u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = { @@ -763,6 +809,14 @@ sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES); rates->supported_mcs_set[0] = 0xFF; } + +void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates) +{ + rates->op_rate_mode = STA_11ac; + rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9; + rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9; +} + static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -926,8 +980,6 @@ out: mutex_unlock(&wcn->conf_mutex); - - return; } /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */ @@ -1075,6 +1127,8 @@ enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; u16 *ssn = ¶ms->ssn; + int ret = 0; + u8 session; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); @@ -1084,10 +1138,11 @@ switch (action) { case IEEE80211_AMPDU_RX_START: sta_priv->tid = tid; - wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, - get_sta_index(vif, sta_priv)); - wcn36xx_smd_add_ba(wcn); - wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv)); + session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0, + get_sta_index(vif, sta_priv)); + wcn36xx_smd_add_ba(wcn, session); + wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid, + session); break; case IEEE80211_AMPDU_RX_STOP: wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv)); @@ -1097,7 +1152,7 @@ sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START; spin_unlock_bh(&sta_priv->ampdu_lock); - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_OPERATIONAL: spin_lock_bh(&sta_priv->ampdu_lock); @@ -1122,7 +1177,7 @@ mutex_unlock(&wcn->conf_mutex); - return 0; + return ret; } static const struct ieee80211_ops wcn36xx_ops = { @@ -1141,6 +1196,8 @@ .set_key = wcn36xx_set_key, .hw_scan = wcn36xx_hw_scan, .cancel_hw_scan = wcn36xx_cancel_hw_scan, + .sw_scan_start = wcn36xx_sw_scan_start, + .sw_scan_complete = wcn36xx_sw_scan_complete, .bss_info_changed = wcn36xx_bss_info_changed, .set_rts_threshold = wcn36xx_set_rts_threshold, .sta_add = wcn36xx_sta_add, @@ -1149,6 +1206,35 @@ CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; + +static void +wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap) +{ + vht_cap->vht_supported = true; + + vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | + 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | + 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); + + vht_cap->vht_mcs.rx_mcs_map = + cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); + + vht_cap->vht_mcs.rx_highest = cpu_to_le16(433); + vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest; + + vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; +} static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) { @@ -1161,11 +1247,11 @@ ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY); ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION); - ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR); 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); + ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS); wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | @@ -1175,6 +1261,9 @@ wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz; if (wcn->rf_id != RF_IRIS_WCN3620) wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; + + if (wcn->rf_id == RF_IRIS_WCN3680) + wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap); wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN; @@ -1273,6 +1362,11 @@ if (iris_node) { if (of_device_is_compatible(iris_node, "qcom,wcn3620")) wcn->rf_id = RF_IRIS_WCN3620; + if (of_device_is_compatible(iris_node, "qcom,wcn3660") || + of_device_is_compatible(iris_node, "qcom,wcn3660b")) + wcn->rf_id = RF_IRIS_WCN3660; + if (of_device_is_compatible(iris_node, "qcom,wcn3680")) + wcn->rf_id = RF_IRIS_WCN3680; of_node_put(iris_node); } @@ -1324,8 +1418,6 @@ wcn36xx_err("failed to set DMA mask: %d\n", ret); goto out_wq; } - - INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker); wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw); if (IS_ERR(wcn->smd_channel)) { -- Gitblit v1.6.2