}
IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
+int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords)
+{
+ return iwl_trans_pcie_read_mem_no_grab(trans, addr, buf, dwords);
+}
+
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
const void *buf, int dwords)
{
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
+/*
+ * Note the special calling convention - it's allowed to drop the
+ * internal transport lock and re-enable BHs temporarily, but will
+ * not release NIC access.
+ */
+int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords);
+
int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
u32 *val);
(bufsize) / sizeof(u32)); \
})
+static inline int
+iwl_trans_read_mem_bytes_no_grab(struct iwl_trans *trans,
+ u32 addr, void *buf, u32 bufsize)
+{
+ return iwl_trans_read_mem_no_grab(trans, addr, buf,
+ bufsize / sizeof(u32));
+}
+
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
u64 src_addr, u32 byte_cnt);
void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val);
int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords);
+int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords);
int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership);
struct iwl_trans_dump_data *
iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
return false;
}
+static void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+ spin_unlock_bh(&trans_pcie->reg_lock);
+ cond_resched();
+ spin_lock_bh(&trans_pcie->reg_lock);
+}
+
void __releases(nic_access_nobh)
iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
{
return 0;
}
+int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
+ void *buf, u32 dwords)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+#define IWL_MAX_HW_ERRS 5
+ unsigned int num_consec_hw_errors = 0;
+ u32 offs = 0;
+ u32 *vals = buf;
+
+ lockdep_assert_held(&trans_pcie->reg_lock);
+
+ while (offs < dwords) {
+ /* limit the time we spin here under lock to 1/2s */
+ unsigned long end = jiffies + HZ / 2;
+ bool resched = false;
+
+ 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)
+ return -EIO;
+
+ offs++;
+
+ if (time_after(jiffies, end)) {
+ resched = true;
+ break;
+ }
+ }
+
+ if (resched)
+ iwl_trans_pcie_resched_with_nic_access(trans);
+ }
+
+ return 0;
+}
+
int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
u32 *val)
{