mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-27 19:32:25 -04:00
wifi: ath12k: Refactor the hardware state
Currently, in multi wiphy models, the mac80211 hardware state is maintained within the radio/link structure. However, in single wiphy models, the mac80211 hardware state is needed at the hardware abstraction layer (ath12k_hw). Therefore, move the hardware state from the radio/link structure to the hardware abstraction layer (ath12k_hw). Additionally, update the naming convention of the state enums to enhance clarity and consistency. 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-3-quic_periyasa@quicinc.com
This commit is contained in:
committed by
Kalle Valo
parent
ecd509b6f2
commit
9b4e5caaf5
@@ -1006,15 +1006,13 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
|
||||
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
ah = ab->ah[i];
|
||||
if (!ah)
|
||||
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
|
||||
continue;
|
||||
|
||||
ieee80211_stop_queues(ah->hw);
|
||||
|
||||
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);
|
||||
@@ -1044,47 +1042,42 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
|
||||
struct ath12k_hw *ah;
|
||||
struct ath12k *ar;
|
||||
int i, j;
|
||||
u8 restart_count;
|
||||
|
||||
for (i = 0; i < ab->num_hw; i++) {
|
||||
ah = ab->ah[i];
|
||||
if (!ah)
|
||||
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
|
||||
continue;
|
||||
|
||||
for (j = 0, restart_count = 0; j < ah->num_radio; j++) {
|
||||
ar = &ah->radio[j];
|
||||
if (ar->state == ATH12K_STATE_OFF)
|
||||
continue;
|
||||
switch (ah->state) {
|
||||
case ATH12K_HW_STATE_ON:
|
||||
ah->state = ATH12K_HW_STATE_RESTARTING;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
for (j = 0; j < ah->num_radio; j++) {
|
||||
ar = &ah->radio[j];
|
||||
|
||||
switch (ar->state) {
|
||||
case ATH12K_STATE_ON:
|
||||
ar->state = ATH12K_STATE_RESTARTING;
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
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)
|
||||
/* Restart after all the link/radio halt */
|
||||
ieee80211_restart_hw(ah->hw);
|
||||
break;
|
||||
case ATH12K_HW_STATE_OFF:
|
||||
ath12k_warn(ab,
|
||||
"cannot restart hw %d that hasn't been started\n",
|
||||
i);
|
||||
break;
|
||||
case ATH12K_HW_STATE_RESTARTING:
|
||||
break;
|
||||
case ATH12K_HW_STATE_RESTARTED:
|
||||
ah->state = ATH12K_HW_STATE_WEDGED;
|
||||
fallthrough;
|
||||
case ATH12K_HW_STATE_WEDGED:
|
||||
ath12k_warn(ab,
|
||||
"device is wedged, will not restart hw %d\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
complete(&ab->driver_recovery);
|
||||
|
||||
@@ -457,12 +457,12 @@ struct ath12k_sta {
|
||||
#define ATH12K_NUM_CHANS 100
|
||||
#define ATH12K_MAX_5G_CHAN 173
|
||||
|
||||
enum ath12k_state {
|
||||
ATH12K_STATE_OFF,
|
||||
ATH12K_STATE_ON,
|
||||
ATH12K_STATE_RESTARTING,
|
||||
ATH12K_STATE_RESTARTED,
|
||||
ATH12K_STATE_WEDGED,
|
||||
enum ath12k_hw_state {
|
||||
ATH12K_HW_STATE_OFF,
|
||||
ATH12K_HW_STATE_ON,
|
||||
ATH12K_HW_STATE_RESTARTING,
|
||||
ATH12K_HW_STATE_RESTARTED,
|
||||
ATH12K_HW_STATE_WEDGED,
|
||||
/* Add other states as required */
|
||||
};
|
||||
|
||||
@@ -511,7 +511,6 @@ struct ath12k {
|
||||
u32 ht_cap_info;
|
||||
u32 vht_cap_info;
|
||||
struct ath12k_he ar_he;
|
||||
enum ath12k_state state;
|
||||
bool supports_6ghz;
|
||||
struct {
|
||||
struct completion started;
|
||||
@@ -636,10 +635,12 @@ struct ath12k {
|
||||
|
||||
struct ath12k_hw {
|
||||
struct ieee80211_hw *hw;
|
||||
struct ath12k_base *ab;
|
||||
enum ath12k_hw_state state;
|
||||
bool regd_updated;
|
||||
bool use_6ghz_regd;
|
||||
|
||||
u8 num_radio;
|
||||
|
||||
struct ath12k radio[] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
@@ -1037,6 +1038,11 @@ static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 hw_link_id
|
||||
return &ah->radio[hw_link_id];
|
||||
}
|
||||
|
||||
static inline struct ath12k_hw *ath12k_ar_to_ah(struct ath12k *ar)
|
||||
{
|
||||
return ar->ah;
|
||||
}
|
||||
|
||||
static inline struct ieee80211_hw *ath12k_ar_to_hw(struct ath12k *ar)
|
||||
{
|
||||
return ar->ah->hw;
|
||||
|
||||
@@ -5269,6 +5269,7 @@ static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
|
||||
|
||||
static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
@@ -5289,8 +5290,8 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
|
||||
ar->cfg_tx_chainmask = tx_ant;
|
||||
ar->cfg_rx_chainmask = rx_ant;
|
||||
|
||||
if (ar->state != ATH12K_STATE_ON &&
|
||||
ar->state != ATH12K_STATE_RESTARTED)
|
||||
if (ah->state != ATH12K_HW_STATE_ON &&
|
||||
ah->state != ATH12K_HW_STATE_RESTARTED)
|
||||
return 0;
|
||||
|
||||
ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_TX_CHAIN_MASK,
|
||||
@@ -5620,22 +5621,6 @@ static int ath12k_mac_start(struct ath12k *ar)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
switch (ar->state) {
|
||||
case ATH12K_STATE_OFF:
|
||||
ar->state = ATH12K_STATE_ON;
|
||||
break;
|
||||
case ATH12K_STATE_RESTARTING:
|
||||
ar->state = ATH12K_STATE_RESTARTED;
|
||||
ath12k_mac_wait_reconfigure(ab);
|
||||
break;
|
||||
case ATH12K_STATE_RESTARTED:
|
||||
case ATH12K_STATE_WEDGED:
|
||||
case ATH12K_STATE_ON:
|
||||
WARN_ON(1);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
|
||||
1, pdev->pdev_id);
|
||||
|
||||
@@ -5726,7 +5711,6 @@ static int ath12k_mac_start(struct ath12k *ar)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
ar->state = ATH12K_STATE_OFF;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
@@ -5749,9 +5733,28 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw)
|
||||
|
||||
ath12k_drain_tx(ah);
|
||||
|
||||
switch (ah->state) {
|
||||
case ATH12K_HW_STATE_OFF:
|
||||
ah->state = ATH12K_HW_STATE_ON;
|
||||
break;
|
||||
case ATH12K_HW_STATE_RESTARTING:
|
||||
ah->state = ATH12K_HW_STATE_RESTARTED;
|
||||
ath12k_mac_wait_reconfigure(ah->ab);
|
||||
break;
|
||||
case ATH12K_HW_STATE_RESTARTED:
|
||||
case ATH12K_HW_STATE_WEDGED:
|
||||
case ATH12K_HW_STATE_ON:
|
||||
ah->state = ATH12K_HW_STATE_OFF;
|
||||
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for_each_ar(ah, ar, i) {
|
||||
ret = ath12k_mac_start(ar);
|
||||
if (ret) {
|
||||
ah->state = ATH12K_HW_STATE_OFF;
|
||||
|
||||
ath12k_err(ar->ab, "fail to start mac operations in pdev idx %d ret %d\n",
|
||||
ar->pdev_idx, ret);
|
||||
goto fail_start;
|
||||
@@ -5759,11 +5762,13 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_start:
|
||||
for (; i > 0; i--) {
|
||||
ar = ath12k_ah_to_ar(ah, i - 1);
|
||||
ath12k_mac_stop(ar);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5836,7 +5841,6 @@ static void ath12k_mac_stop(struct ath12k *ar)
|
||||
ret);
|
||||
|
||||
clear_bit(ATH12K_CAC_RUNNING, &ar->dev_flags);
|
||||
ar->state = ATH12K_STATE_OFF;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
@@ -5865,6 +5869,8 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
|
||||
|
||||
ath12k_drain_tx(ah);
|
||||
|
||||
ah->state = ATH12K_HW_STATE_OFF;
|
||||
|
||||
for_each_ar(ah, ar, i)
|
||||
ath12k_mac_stop(ar);
|
||||
}
|
||||
@@ -7925,22 +7931,20 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
|
||||
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
|
||||
return;
|
||||
|
||||
if (ah->state != ATH12K_HW_STATE_RESTARTED)
|
||||
return;
|
||||
|
||||
ah->state = ATH12K_HW_STATE_ON;
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
for_each_ar(ah, ar, i) {
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH12K_STATE_RESTARTED) {
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
ab = ar->ab;
|
||||
|
||||
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);
|
||||
|
||||
@@ -8926,6 +8930,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
|
||||
|
||||
ah = ath12k_hw_to_ah(hw);
|
||||
ah->hw = hw;
|
||||
ah->ab = ab;
|
||||
ah->num_radio = num_pdev_map;
|
||||
|
||||
for (i = 0; i < num_pdev_map; i++) {
|
||||
|
||||
@@ -206,9 +206,9 @@ static void ath12k_copy_regd(struct ieee80211_regdomain *regd_orig,
|
||||
|
||||
int ath12k_regd_update(struct ath12k *ar, bool init)
|
||||
{
|
||||
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
|
||||
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
|
||||
struct ieee80211_hw *hw = ah->hw;
|
||||
struct ieee80211_regdomain *regd, *regd_copy = NULL;
|
||||
struct ath12k_hw *ah = ar->ah;
|
||||
int ret, regd_len, pdev_id;
|
||||
struct ath12k_base *ab;
|
||||
int i;
|
||||
@@ -286,19 +286,20 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (ah->state != ATH12K_HW_STATE_ON)
|
||||
goto skip;
|
||||
|
||||
ah->regd_updated = true;
|
||||
/* Apply the new regd to all the radios, this is expected to be received only once
|
||||
* since we check for ah->regd_updated and allow here only once.
|
||||
*/
|
||||
for_each_ar(ah, ar, i) {
|
||||
if (ar->state == ATH12K_STATE_ON) {
|
||||
ab = ar->ab;
|
||||
ret = ath12k_reg_update_chan_list(ar);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
ab = ar->ab;
|
||||
ret = ath12k_reg_update_chan_list(ar);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
skip:
|
||||
return 0;
|
||||
err:
|
||||
ath12k_warn(ab, "failed to perform regd update : %d\n", ret);
|
||||
|
||||
Reference in New Issue
Block a user