wifi: iwlwifi: pcie: implement iwl_trans_pcie_gen3_read_mem
Add a gen3-specific implementation of iwl_trans_pcie_read_mem
type=feature
ticket=none
Signed-off-by: Rotem Kerem <rotem.kerem@intel.com>
Change-Id: Ib51603750873bb2ec1fcf69a4630b6b169f8bdaa
Reviewed-on: https://gerritwcs.ir.intel.com/c/iwlwifi-stack-dev/+/197778
automatic-review: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM>
Tested-by: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM>
tested: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM>
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
x-iwlwifi-stack-dev: 9539694fcab40fcd4ffa1dee8878a0c92febff78
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
index f6d6e55..4327163 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -485,7 +485,10 @@
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords)
{
- return iwl_trans_pcie_read_mem(trans, addr, buf, dwords);
+ if (trans->mac_cfg->gen3)
+ return iwl_trans_pcie_gen3_read_mem(trans, addr, buf, dwords);
+ else
+ return iwl_trans_pcie_read_mem(trans, addr, buf, dwords);
}
IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.c
index f663f34..b58c6e1 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.c
@@ -200,3 +200,55 @@
__release(nic_access);
spin_unlock(&trans_pcie->reg_lock);
}
+
+int iwl_trans_pcie_gen3_read_mem(struct iwl_trans *trans, u32 addr,
+ void *buf, int dwords)
+{
+#define IWL_MAX_HW_ERRS 5
+ unsigned int num_consec_hw_errors = 0;
+ int offs = 0;
+ u32 *vals = buf;
+
+ /* TODO: add support for Vlab (task=vlab) */
+
+ while (offs < dwords) {
+ /* limit the time we spin here under lock to 1/2s */
+ unsigned long end = jiffies + HZ / 2;
+ bool resched = false;
+
+ if (iwl_trans_grab_nic_access(trans)) {
+ iwl_write32(trans, HBUS_TARG_MEM_RADDR,
+ addr + 4 * offs);
+
+ while (offs < dwords) {
+ vals[offs] = iwl_read32(trans,
+ HBUS_TARG_MEM_RDAT);
+
+ if (iwl_trans_is_hw_error_value(vals[offs]))
+ num_consec_hw_errors++;
+ else
+ num_consec_hw_errors = 0;
+
+ if (num_consec_hw_errors >= IWL_MAX_HW_ERRS) {
+ iwl_trans_release_nic_access(trans);
+ return -EIO;
+ }
+
+ offs++;
+
+ if (time_after(jiffies, end)) {
+ resched = true;
+ break;
+ }
+ }
+ iwl_trans_release_nic_access(trans);
+
+ if (resched)
+ cond_resched();
+ } else {
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.h
index bdf3ef3..ef5705e 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen3/trans.h
@@ -101,5 +101,7 @@
bool iwl_trans_pcie_gen3_grab_nic_access(struct iwl_trans *trans);
void __releases(nic_access)
iwl_trans_pcie_gen3_release_nic_access(struct iwl_trans *trans);
+int iwl_trans_pcie_gen3_read_mem(struct iwl_trans *trans, u32 addr,
+ void *buf, int dwords);
#endif /* __iwl_trans_pcie_gen3_h__ */
diff --git a/versions b/versions
index b97e24a..9a74b2b 100644
--- a/versions
+++ b/versions
@@ -2,4 +2,4 @@
BACKPORTED_KERNEL_VERSION="(see git)"
BACKPORTED_KERNEL_NAME="iwlwifi"
BACKPORTS_BUILD_TSTAMP=__DATE__ \" \" __TIME__
-BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:13855:ceca704e"
+BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:13856:9539694f"