wifi: ath12k: flush all packets before suspend
In order to send out all packets before going to suspend, current code adds a 500ms delay as a workaround. It is a rough estimate and may not work. Fix this by checking packet counters, if counters become zero, then all packets are sent out or dropped. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://msgid.link/20240412060620.27519-7-quic_bqiang@quicinc.com
This commit is contained in:
parent
7b3d4eb283
commit
692921ead8
3 changed files with 38 additions and 11 deletions
|
@ -44,15 +44,25 @@ static int ath12k_core_rfkill_config(struct ath12k_base *ab)
|
||||||
|
|
||||||
int ath12k_core_suspend(struct ath12k_base *ab)
|
int ath12k_core_suspend(struct ath12k_base *ab)
|
||||||
{
|
{
|
||||||
int ret;
|
struct ath12k *ar;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
if (!ab->hw_params->supports_suspend)
|
if (!ab->hw_params->supports_suspend)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
/* TODO: there can frames in queues so for now add delay as a hack.
|
rcu_read_lock();
|
||||||
* Need to implement to handle and remove this delay.
|
for (i = 0; i < ab->num_radios; i++) {
|
||||||
*/
|
ar = ath12k_mac_get_ar_by_pdev_id(ab, i);
|
||||||
msleep(500);
|
if (!ar)
|
||||||
|
continue;
|
||||||
|
ret = ath12k_mac_wait_tx_complete(ar);
|
||||||
|
if (ret) {
|
||||||
|
ath12k_warn(ab, "failed to wait tx complete: %d\n", ret);
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
ret = ath12k_dp_rx_pktlog_stop(ab, true);
|
ret = ath12k_dp_rx_pktlog_stop(ab, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -7417,22 +7417,38 @@ static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath12k_mac_flush(struct ath12k *ar)
|
static int ath12k_mac_flush(struct ath12k *ar)
|
||||||
{
|
{
|
||||||
long time_left;
|
long time_left;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
|
time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
|
||||||
(atomic_read(&ar->dp.num_tx_pending) == 0),
|
(atomic_read(&ar->dp.num_tx_pending) == 0),
|
||||||
ATH12K_FLUSH_TIMEOUT);
|
ATH12K_FLUSH_TIMEOUT);
|
||||||
if (time_left == 0)
|
if (time_left == 0) {
|
||||||
ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
|
ath12k_warn(ar->ab,
|
||||||
|
"failed to flush transmit queue, data pkts pending %d\n",
|
||||||
|
atomic_read(&ar->dp.num_tx_pending));
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
|
time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
|
||||||
(atomic_read(&ar->num_pending_mgmt_tx) == 0),
|
(atomic_read(&ar->num_pending_mgmt_tx) == 0),
|
||||||
ATH12K_FLUSH_TIMEOUT);
|
ATH12K_FLUSH_TIMEOUT);
|
||||||
if (time_left == 0)
|
if (time_left == 0) {
|
||||||
ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
|
ath12k_warn(ar->ab,
|
||||||
time_left);
|
"failed to flush mgmt transmit queue, mgmt pkts pending %d\n",
|
||||||
|
atomic_read(&ar->num_pending_mgmt_tx));
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ath12k_mac_wait_tx_complete(struct ath12k *ar)
|
||||||
|
{
|
||||||
|
ath12k_mac_drain_tx(ar);
|
||||||
|
return ath12k_mac_flush(ar);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||||
|
|
|
@ -78,4 +78,5 @@ enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw b
|
||||||
enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher);
|
enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher);
|
||||||
int ath12k_mac_rfkill_enable_radio(struct ath12k *ar, bool enable);
|
int ath12k_mac_rfkill_enable_radio(struct ath12k *ar, bool enable);
|
||||||
int ath12k_mac_rfkill_config(struct ath12k *ar);
|
int ath12k_mac_rfkill_config(struct ath12k *ar);
|
||||||
|
int ath12k_mac_wait_tx_complete(struct ath12k *ar);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue