wifi: ath12k: Refactor the hardware recovery procedure
Currently, in multi-wiphy models, the recovery handler access mac80211 HW from the radio/link structure. This will be incorrect for single wiphy model, as they will hold multiple link/radio structures. To fix this, access mac80211 HW based on the number of hardware in the SoC/chip. This approach makes the recovery handler compatible with both multi wiphy and single wiphy models. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://msgid.link/20240425090307.3233434-2-quic_periyasa@quicinc.com
This commit is contained in:
parent
f41c7cab87
commit
ecd509b6f2
2 changed files with 80 additions and 62 deletions
|
@ -994,9 +994,8 @@ void ath12k_core_halt(struct ath12k *ar)
|
|||
static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k *ar;
|
||||
struct ath12k_pdev *pdev;
|
||||
struct ath12k_hw *ah;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
ab->stats.fw_crash_counter++;
|
||||
|
@ -1006,35 +1005,34 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
|||
set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
if (!ab->ah[i])
|
||||
continue;
|
||||
|
||||
ah = ab->ah[i];
|
||||
ieee80211_stop_queues(ah->hw);
|
||||
}
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
if (!ar || ar->state == ATH12K_STATE_OFF)
|
||||
if (!ah)
|
||||
continue;
|
||||
|
||||
ath12k_mac_drain_tx(ar);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
complete(&ar->install_key_done);
|
||||
complete(&ar->vdev_setup_done);
|
||||
complete(&ar->vdev_delete_done);
|
||||
complete(&ar->bss_survey_done);
|
||||
ieee80211_stop_queues(ah->hw);
|
||||
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
ath12k_mac_tx_mgmt_pending_free, ar);
|
||||
idr_destroy(&ar->txmgmt_idr);
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
for (j = 0; j < ah->num_radio; j++) {
|
||||
ar = &ah->radio[j];
|
||||
if (ar->state == ATH12K_STATE_OFF)
|
||||
continue;
|
||||
|
||||
ath12k_mac_drain_tx(ar);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
complete(&ar->install_key_done);
|
||||
complete(&ar->vdev_setup_done);
|
||||
complete(&ar->vdev_delete_done);
|
||||
complete(&ar->bss_survey_done);
|
||||
|
||||
wake_up(&ar->dp.tx_empty_waitq);
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
ath12k_mac_tx_mgmt_pending_free, ar);
|
||||
idr_destroy(&ar->txmgmt_idr);
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
}
|
||||
}
|
||||
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
|
@ -1043,41 +1041,52 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
|||
|
||||
static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
|
||||
{
|
||||
struct ath12k_hw *ah;
|
||||
struct ath12k *ar;
|
||||
struct ath12k_pdev *pdev;
|
||||
int i;
|
||||
int i, j;
|
||||
u8 restart_count;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
if (!ar || ar->state == ATH12K_STATE_OFF)
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
ah = ab->ah[i];
|
||||
if (!ah)
|
||||
continue;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
for (j = 0, restart_count = 0; j < ah->num_radio; j++) {
|
||||
ar = &ah->radio[j];
|
||||
if (ar->state == ATH12K_STATE_OFF)
|
||||
continue;
|
||||
|
||||
switch (ar->state) {
|
||||
case ATH12K_STATE_ON:
|
||||
ar->state = ATH12K_STATE_RESTARTING;
|
||||
ath12k_core_halt(ar);
|
||||
ieee80211_restart_hw(ath12k_ar_to_hw(ar));
|
||||
break;
|
||||
case ATH12K_STATE_OFF:
|
||||
ath12k_warn(ab,
|
||||
"cannot restart radio %d that hasn't been started\n",
|
||||
i);
|
||||
break;
|
||||
case ATH12K_STATE_RESTARTING:
|
||||
break;
|
||||
case ATH12K_STATE_RESTARTED:
|
||||
ar->state = ATH12K_STATE_WEDGED;
|
||||
fallthrough;
|
||||
case ATH12K_STATE_WEDGED:
|
||||
ath12k_warn(ab,
|
||||
"device is wedged, will not restart radio %d\n", i);
|
||||
break;
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
switch (ar->state) {
|
||||
case ATH12K_STATE_ON:
|
||||
ar->state = ATH12K_STATE_RESTARTING;
|
||||
ath12k_core_halt(ar);
|
||||
restart_count++;
|
||||
break;
|
||||
case ATH12K_STATE_OFF:
|
||||
ath12k_warn(ab,
|
||||
"cannot restart radio %d that hasn't been started\n",
|
||||
j);
|
||||
break;
|
||||
case ATH12K_STATE_RESTARTING:
|
||||
break;
|
||||
case ATH12K_STATE_RESTARTED:
|
||||
ar->state = ATH12K_STATE_WEDGED;
|
||||
fallthrough;
|
||||
case ATH12K_STATE_WEDGED:
|
||||
ath12k_warn(ab,
|
||||
"device is wedged, will not restart radio %d\n", j);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
/* Restart after all the link/radio got restart */
|
||||
if (restart_count == ah->num_radio)
|
||||
ieee80211_restart_hw(ah->hw);
|
||||
}
|
||||
|
||||
complete(&ab->driver_recovery);
|
||||
}
|
||||
|
||||
|
|
|
@ -7920,26 +7920,33 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
|
|||
struct ath12k *ar;
|
||||
struct ath12k_base *ab;
|
||||
struct ath12k_vif *arvif;
|
||||
int recovery_count;
|
||||
int recovery_count, i;
|
||||
|
||||
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
|
||||
return;
|
||||
|
||||
ar = ath12k_ah_to_ar(ah, 0);
|
||||
ab = ar->ab;
|
||||
for_each_ar(ah, ar, i) {
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
if (ar->state != ATH12K_STATE_RESTARTED) {
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
ab = ar->ab;
|
||||
|
||||
if (ar->state == ATH12K_STATE_RESTARTED) {
|
||||
ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
|
||||
ar->pdev->pdev_id);
|
||||
|
||||
ar->state = ATH12K_STATE_ON;
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
if (ab->is_reset) {
|
||||
recovery_count = atomic_inc_return(&ab->recovery_count);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "recovery count %d\n",
|
||||
recovery_count);
|
||||
|
||||
/* When there are multiple radios in an SOC,
|
||||
* the recovery has to be done for each radio
|
||||
*/
|
||||
|
@ -7958,6 +7965,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
|
|||
arvif->key_cipher,
|
||||
arvif->is_up,
|
||||
arvif->vdev_type);
|
||||
|
||||
/* After trigger disconnect, then upper layer will
|
||||
* trigger connect again, then the PN number of
|
||||
* upper layer will be reset to keep up with AP
|
||||
|
@ -7967,13 +7975,14 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
|
|||
arvif->vdev_type == WMI_VDEV_TYPE_STA &&
|
||||
arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
|
||||
ieee80211_hw_restart_disconnect(arvif->vif);
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"restart disconnect\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Add table
Reference in a new issue