Skip to content

Commit 4f479cb

Browse files
jmberg-intelMiriam-Rachel
authored andcommitted
wifi: iwlwifi: transport: add memory read under NIC access
Add functions to be able to do memory read under NIC access, in order to use them later during firmware dump. These may drop and re-acquire the spinlock, but will not acquire and release the NIC access. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Link: https://patch.msgid.link/20260517100550.7bb1ea51c347.I91420a24fb0c481c75a2600d60e1365c15c1c5a9@changeid Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
1 parent 90b2f28 commit 4f479cb

4 files changed

Lines changed: 78 additions & 0 deletions

File tree

drivers/net/wireless/intel/iwlwifi/iwl-trans.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,12 @@ int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
459459
}
460460
IWL_EXPORT_SYMBOL(iwl_trans_read_mem);
461461

462+
int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
463+
void *buf, u32 dwords)
464+
{
465+
return iwl_trans_pcie_read_mem_no_grab(trans, addr, buf, dwords);
466+
}
467+
462468
int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
463469
const void *buf, int dwords)
464470
{

drivers/net/wireless/intel/iwlwifi/iwl-trans.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,14 @@ void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
919919
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
920920
void *buf, int dwords);
921921

922+
/*
923+
* Note the special calling convention - it's allowed to drop the
924+
* internal transport lock and re-enable BHs temporarily, but will
925+
* not release NIC access.
926+
*/
927+
int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
928+
void *buf, u32 dwords);
929+
922930
int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
923931
u32 *val);
924932

@@ -934,6 +942,14 @@ void iwl_trans_debugfs_cleanup(struct iwl_trans *trans);
934942
(bufsize) / sizeof(u32)); \
935943
})
936944

945+
static inline int
946+
iwl_trans_read_mem_bytes_no_grab(struct iwl_trans *trans,
947+
u32 addr, void *buf, u32 bufsize)
948+
{
949+
return iwl_trans_read_mem_no_grab(trans, addr, buf,
950+
bufsize / sizeof(u32));
951+
}
952+
937953
int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr,
938954
u64 src_addr, u32 byte_cnt);
939955

drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,8 @@ u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg);
11861186
void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val);
11871187
int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
11881188
void *buf, int dwords);
1189+
int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
1190+
void *buf, u32 dwords);
11891191
int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership);
11901192
struct iwl_trans_dump_data *
11911193
iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,

drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,15 @@ bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
24242424
return false;
24252425
}
24262426

2427+
static void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans)
2428+
{
2429+
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
2430+
2431+
spin_unlock_bh(&trans_pcie->reg_lock);
2432+
cond_resched();
2433+
spin_lock_bh(&trans_pcie->reg_lock);
2434+
}
2435+
24272436
void __releases(nic_access_nobh)
24282437
iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
24292438
{
@@ -2506,6 +2515,51 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
25062515
return 0;
25072516
}
25082517

2518+
int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr,
2519+
void *buf, u32 dwords)
2520+
{
2521+
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
2522+
#define IWL_MAX_HW_ERRS 5
2523+
unsigned int num_consec_hw_errors = 0;
2524+
u32 offs = 0;
2525+
u32 *vals = buf;
2526+
2527+
lockdep_assert_held(&trans_pcie->reg_lock);
2528+
2529+
while (offs < dwords) {
2530+
/* limit the time we spin here under lock to 1/2s */
2531+
unsigned long end = jiffies + HZ / 2;
2532+
bool resched = false;
2533+
2534+
iwl_write32(trans, HBUS_TARG_MEM_RADDR,
2535+
addr + 4 * offs);
2536+
2537+
while (offs < dwords) {
2538+
vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
2539+
2540+
if (iwl_trans_is_hw_error_value(vals[offs]))
2541+
num_consec_hw_errors++;
2542+
else
2543+
num_consec_hw_errors = 0;
2544+
2545+
if (num_consec_hw_errors >= IWL_MAX_HW_ERRS)
2546+
return -EIO;
2547+
2548+
offs++;
2549+
2550+
if (time_after(jiffies, end)) {
2551+
resched = true;
2552+
break;
2553+
}
2554+
}
2555+
2556+
if (resched)
2557+
iwl_trans_pcie_resched_with_nic_access(trans);
2558+
}
2559+
2560+
return 0;
2561+
}
2562+
25092563
int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs,
25102564
u32 *val)
25112565
{

0 commit comments

Comments
 (0)