diff options
author | Johannes Berg <johannes.berg@intel.com> | 2019-10-19 06:03:29 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2019-10-23 06:31:33 -0400 |
commit | 91cf5dede57f9c4030c1378745d612eec2075652 (patch) | |
tree | 5f15163d1b519ebd5c121c8cde8b8f9aa00b5d2f | |
parent | e55890150a961944e861a46efc8599f80f25de76 (diff) |
iwlwifi: mvm: handle iwl_mvm_tvqm_enable_txq() error return
iwl_mvm_tvqm_enable_txq() can return an error, notably if unable
to allocate memory for the queue. Handle this error throughout,
avoiding storing the invalid value into a u16 which later leads
to a disable of an invalid queue ("queue 65524 not used", where
65524 is just -ENOMEM in a u16).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 140 |
1 files changed, 83 insertions, 57 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 0bedba4c61f2..b3768d5d852a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c | |||
@@ -1482,6 +1482,13 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, | |||
1482 | mvm_sta->sta_id, i); | 1482 | mvm_sta->sta_id, i); |
1483 | txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id, | 1483 | txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id, |
1484 | i, wdg); | 1484 | i, wdg); |
1485 | /* | ||
1486 | * on failures, just set it to IWL_MVM_INVALID_QUEUE | ||
1487 | * to try again later, we have no other good way of | ||
1488 | * failing here | ||
1489 | */ | ||
1490 | if (txq_id < 0) | ||
1491 | txq_id = IWL_MVM_INVALID_QUEUE; | ||
1485 | tid_data->txq_id = txq_id; | 1492 | tid_data->txq_id = txq_id; |
1486 | 1493 | ||
1487 | /* | 1494 | /* |
@@ -1950,30 +1957,73 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta) | |||
1950 | sta->sta_id = IWL_MVM_INVALID_STA; | 1957 | sta->sta_id = IWL_MVM_INVALID_STA; |
1951 | } | 1958 | } |
1952 | 1959 | ||
1953 | static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue, | 1960 | static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue, |
1954 | u8 sta_id, u8 fifo) | 1961 | u8 sta_id, u8 fifo) |
1955 | { | 1962 | { |
1956 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | 1963 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? |
1957 | mvm->trans->trans_cfg->base_params->wd_timeout : | 1964 | mvm->trans->trans_cfg->base_params->wd_timeout : |
1958 | IWL_WATCHDOG_DISABLED; | 1965 | IWL_WATCHDOG_DISABLED; |
1966 | struct iwl_trans_txq_scd_cfg cfg = { | ||
1967 | .fifo = fifo, | ||
1968 | .sta_id = sta_id, | ||
1969 | .tid = IWL_MAX_TID_COUNT, | ||
1970 | .aggregate = false, | ||
1971 | .frame_limit = IWL_FRAME_LIMIT, | ||
1972 | }; | ||
1973 | |||
1974 | WARN_ON(iwl_mvm_has_new_tx_api(mvm)); | ||
1975 | |||
1976 | iwl_mvm_enable_txq(mvm, NULL, queue, 0, &cfg, wdg_timeout); | ||
1977 | } | ||
1978 | |||
1979 | static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id) | ||
1980 | { | ||
1981 | unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? | ||
1982 | mvm->trans->trans_cfg->base_params->wd_timeout : | ||
1983 | IWL_WATCHDOG_DISABLED; | ||
1984 | |||
1985 | WARN_ON(!iwl_mvm_has_new_tx_api(mvm)); | ||
1986 | |||
1987 | return iwl_mvm_tvqm_enable_txq(mvm, sta_id, IWL_MAX_TID_COUNT, | ||
1988 | wdg_timeout); | ||
1989 | } | ||
1959 | 1990 | ||
1991 | static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx, | ||
1992 | int maccolor, | ||
1993 | struct iwl_mvm_int_sta *sta, | ||
1994 | u16 *queue, int fifo) | ||
1995 | { | ||
1996 | int ret; | ||
1997 | |||
1998 | /* Map queue to fifo - needs to happen before adding station */ | ||
1999 | if (!iwl_mvm_has_new_tx_api(mvm)) | ||
2000 | iwl_mvm_enable_aux_snif_queue(mvm, *queue, sta->sta_id, fifo); | ||
2001 | |||
2002 | ret = iwl_mvm_add_int_sta_common(mvm, sta, NULL, macidx, maccolor); | ||
2003 | if (ret) { | ||
2004 | if (!iwl_mvm_has_new_tx_api(mvm)) | ||
2005 | iwl_mvm_disable_txq(mvm, NULL, *queue, | ||
2006 | IWL_MAX_TID_COUNT, 0); | ||
2007 | return ret; | ||
2008 | } | ||
2009 | |||
2010 | /* | ||
2011 | * For 22000 firmware and on we cannot add queue to a station unknown | ||
2012 | * to firmware so enable queue here - after the station was added | ||
2013 | */ | ||
1960 | if (iwl_mvm_has_new_tx_api(mvm)) { | 2014 | if (iwl_mvm_has_new_tx_api(mvm)) { |
1961 | int tvqm_queue = | 2015 | int txq; |
1962 | iwl_mvm_tvqm_enable_txq(mvm, sta_id, | ||
1963 | IWL_MAX_TID_COUNT, | ||
1964 | wdg_timeout); | ||
1965 | *queue = tvqm_queue; | ||
1966 | } else { | ||
1967 | struct iwl_trans_txq_scd_cfg cfg = { | ||
1968 | .fifo = fifo, | ||
1969 | .sta_id = sta_id, | ||
1970 | .tid = IWL_MAX_TID_COUNT, | ||
1971 | .aggregate = false, | ||
1972 | .frame_limit = IWL_FRAME_LIMIT, | ||
1973 | }; | ||
1974 | 2016 | ||
1975 | iwl_mvm_enable_txq(mvm, NULL, *queue, 0, &cfg, wdg_timeout); | 2017 | txq = iwl_mvm_enable_aux_snif_queue_tvqm(mvm, sta->sta_id); |
2018 | if (txq < 0) { | ||
2019 | iwl_mvm_rm_sta_common(mvm, sta->sta_id); | ||
2020 | return txq; | ||
2021 | } | ||
2022 | |||
2023 | *queue = txq; | ||
1976 | } | 2024 | } |
2025 | |||
2026 | return 0; | ||
1977 | } | 2027 | } |
1978 | 2028 | ||
1979 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) | 2029 | int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) |
@@ -1989,59 +2039,26 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) | |||
1989 | if (ret) | 2039 | if (ret) |
1990 | return ret; | 2040 | return ret; |
1991 | 2041 | ||
1992 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ | 2042 | ret = iwl_mvm_add_int_sta_with_queue(mvm, MAC_INDEX_AUX, 0, |
1993 | if (!iwl_mvm_has_new_tx_api(mvm)) | 2043 | &mvm->aux_sta, &mvm->aux_queue, |
1994 | iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue, | 2044 | IWL_MVM_TX_FIFO_MCAST); |
1995 | mvm->aux_sta.sta_id, | ||
1996 | IWL_MVM_TX_FIFO_MCAST); | ||
1997 | |||
1998 | ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL, | ||
1999 | MAC_INDEX_AUX, 0); | ||
2000 | if (ret) { | 2045 | if (ret) { |
2001 | iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta); | 2046 | iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta); |
2002 | return ret; | 2047 | return ret; |
2003 | } | 2048 | } |
2004 | 2049 | ||
2005 | /* | ||
2006 | * For 22000 firmware and on we cannot add queue to a station unknown | ||
2007 | * to firmware so enable queue here - after the station was added | ||
2008 | */ | ||
2009 | if (iwl_mvm_has_new_tx_api(mvm)) | ||
2010 | iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue, | ||
2011 | mvm->aux_sta.sta_id, | ||
2012 | IWL_MVM_TX_FIFO_MCAST); | ||
2013 | |||
2014 | return 0; | 2050 | return 0; |
2015 | } | 2051 | } |
2016 | 2052 | ||
2017 | int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 2053 | int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
2018 | { | 2054 | { |
2019 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 2055 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
2020 | int ret; | ||
2021 | 2056 | ||
2022 | lockdep_assert_held(&mvm->mutex); | 2057 | lockdep_assert_held(&mvm->mutex); |
2023 | 2058 | ||
2024 | /* Map snif queue to fifo - must happen before adding snif station */ | 2059 | return iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color, |
2025 | if (!iwl_mvm_has_new_tx_api(mvm)) | 2060 | &mvm->snif_sta, &mvm->snif_queue, |
2026 | iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue, | ||
2027 | mvm->snif_sta.sta_id, | ||
2028 | IWL_MVM_TX_FIFO_BE); | 2061 | IWL_MVM_TX_FIFO_BE); |
2029 | |||
2030 | ret = iwl_mvm_add_int_sta_common(mvm, &mvm->snif_sta, vif->addr, | ||
2031 | mvmvif->id, 0); | ||
2032 | if (ret) | ||
2033 | return ret; | ||
2034 | |||
2035 | /* | ||
2036 | * For 22000 firmware and on we cannot add queue to a station unknown | ||
2037 | * to firmware so enable queue here - after the station was added | ||
2038 | */ | ||
2039 | if (iwl_mvm_has_new_tx_api(mvm)) | ||
2040 | iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue, | ||
2041 | mvm->snif_sta.sta_id, | ||
2042 | IWL_MVM_TX_FIFO_BE); | ||
2043 | |||
2044 | return 0; | ||
2045 | } | 2062 | } |
2046 | 2063 | ||
2047 | int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 2064 | int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
@@ -2133,6 +2150,10 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2133 | queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id, | 2150 | queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id, |
2134 | IWL_MAX_TID_COUNT, | 2151 | IWL_MAX_TID_COUNT, |
2135 | wdg_timeout); | 2152 | wdg_timeout); |
2153 | if (queue < 0) { | ||
2154 | iwl_mvm_rm_sta_common(mvm, bsta->sta_id); | ||
2155 | return queue; | ||
2156 | } | ||
2136 | 2157 | ||
2137 | if (vif->type == NL80211_IFTYPE_AP || | 2158 | if (vif->type == NL80211_IFTYPE_AP || |
2138 | vif->type == NL80211_IFTYPE_ADHOC) | 2159 | vif->type == NL80211_IFTYPE_ADHOC) |
@@ -2307,10 +2328,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2307 | } | 2328 | } |
2308 | ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr, | 2329 | ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr, |
2309 | mvmvif->id, mvmvif->color); | 2330 | mvmvif->id, mvmvif->color); |
2310 | if (ret) { | 2331 | if (ret) |
2311 | iwl_mvm_dealloc_int_sta(mvm, msta); | 2332 | goto err; |
2312 | return ret; | ||
2313 | } | ||
2314 | 2333 | ||
2315 | /* | 2334 | /* |
2316 | * Enable cab queue after the ADD_STA command is sent. | 2335 | * Enable cab queue after the ADD_STA command is sent. |
@@ -2323,6 +2342,10 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2323 | int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id, | 2342 | int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id, |
2324 | 0, | 2343 | 0, |
2325 | timeout); | 2344 | timeout); |
2345 | if (queue < 0) { | ||
2346 | ret = queue; | ||
2347 | goto err; | ||
2348 | } | ||
2326 | mvmvif->cab_queue = queue; | 2349 | mvmvif->cab_queue = queue; |
2327 | } else if (!fw_has_api(&mvm->fw->ucode_capa, | 2350 | } else if (!fw_has_api(&mvm->fw->ucode_capa, |
2328 | IWL_UCODE_TLV_API_STA_TYPE)) | 2351 | IWL_UCODE_TLV_API_STA_TYPE)) |
@@ -2330,6 +2353,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
2330 | timeout); | 2353 | timeout); |
2331 | 2354 | ||
2332 | return 0; | 2355 | return 0; |
2356 | err: | ||
2357 | iwl_mvm_dealloc_int_sta(mvm, msta); | ||
2358 | return ret; | ||
2333 | } | 2359 | } |
2334 | 2360 | ||
2335 | static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, | 2361 | static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, |