]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
iwlwifi: Set w-pointer upon resume according to SN
authorAlex Malamud <alex.malamud@intel.com>
Mon, 10 Jun 2019 12:19:23 +0000 (15:19 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 6 Sep 2019 12:31:16 +0000 (15:31 +0300)
During D3 state, FW may send packets.
As a result, "write" queue pointer will be incremented by FW.
Upon resume from D3, driver should adjust its shadows of "write" and "read"
pointers to the value reported by FW.

1. Keep TID used during wowlan configuration.
2. Upon resume, set driver's "write" and "read" queue pointers
to the value reported by FW.

Signed-off-by: Alex Malamud <alex.malamud@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index 942662eaf523a625ce71d257448e6ed30a7c8a66..034c935b5579cfbb9618a00b41c8afdbcc058690 100644 (file)
@@ -562,6 +562,8 @@ struct iwl_trans_ops {
        void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
                        struct sk_buff_head *skbs);
 
+       void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr);
+
        bool (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
                           const struct iwl_trans_txq_scd_cfg *cfg,
                           unsigned int queue_wdg_timeout);
@@ -999,6 +1001,17 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
        trans->ops->reclaim(trans, queue, ssn, skbs);
 }
 
+static inline void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue,
+                                       int ptr)
+{
+       if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
+               IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
+               return;
+       }
+
+       trans->ops->set_q_ptrs(trans, queue, ptr);
+}
+
 static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue,
                                         bool configure_scd)
 {
index 89839a83d8c2a488a6801efd8e9770fc364b784a..6f7345b121a614b74d9bce9a64ef4b314d45ada2 100644 (file)
@@ -831,6 +831,8 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
        bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
                                         IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
 
+       mvm->offload_tid = wowlan_config_cmd->offloading_tid;
+
        if (!unified_image) {
                ret = iwl_mvm_switch_to_d3(mvm);
                if (ret)
@@ -1656,6 +1658,13 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
                mvm_ap_sta->tid_data[i].seq_number = seq;
        }
 
+       if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+               i = mvm->offload_tid;
+               iwl_trans_set_q_ptrs(mvm->trans,
+                                    mvm_ap_sta->tid_data[i].txq_id,
+                                    mvm_ap_sta->tid_data[i].seq_number >> 4);
+       }
+
        /* now we have all the data we need, unlock to avoid mac80211 issues */
        mutex_unlock(&mvm->mutex);
 
index 3efcc3a939b87de73db97386bae77685b43cbdb7..79bbdf8121cc26e8186089ca925a4504c30fcb04 100644 (file)
@@ -1001,6 +1001,7 @@ struct iwl_mvm {
        struct ieee80211_channel **nd_channels;
        int n_nd_channels;
        bool net_detect;
+       u8 offload_tid;
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        bool d3_wake_sysassert;
        bool d3_test_active;
index 9f5d0fc839fef32beb091d528089a77a83bdad88..6bf2a816e221468f41a3ce49a5cad9522d3eb957 100644 (file)
@@ -697,6 +697,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
                            struct iwl_rx_cmd_buffer *rxb);
 void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
                            struct sk_buff_head *skbs);
+void iwl_trans_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr);
 void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
 void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans_pcie *trans_pcie,
                                   struct iwl_txq *txq, u16 byte_cnt,
index 1bbbf978245db2b5555ff38956a288d4c9a5bfa6..59b72a8de737465e8faa31f90921d1112c7c28af 100644 (file)
@@ -3397,6 +3397,8 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
        .tx = iwl_trans_pcie_gen2_tx,
        .reclaim = iwl_trans_pcie_reclaim,
 
+       .set_q_ptrs = iwl_trans_pcie_set_q_ptrs,
+
        .txq_alloc = iwl_trans_pcie_dyn_txq_alloc,
        .txq_free = iwl_trans_pcie_dyn_txq_free,
        .wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
index 2f0ba7ef53b8616a4bf4581b49106cf0094739ad..b25f51b5893cb30f8830c2cd539e93f2f51362eb 100644 (file)
@@ -1234,6 +1234,20 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
        spin_unlock_bh(&txq->lock);
 }
 
+/* Set wr_ptr of specific device and txq  */
+void iwl_trans_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_txq *txq = trans_pcie->txq[txq_id];
+
+       spin_lock_bh(&txq->lock);
+
+       txq->write_ptr = ptr;
+       txq->read_ptr = txq->write_ptr;
+
+       spin_unlock_bh(&txq->lock);
+}
+
 static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
                                      const struct iwl_host_cmd *cmd)
 {