Oliver Neukum e6380b
From 3d372c4edfd4dffb7dea71c6b096fb414782b776 Mon Sep 17 00:00:00 2001
Oliver Neukum e6380b
From: Johannes Berg <johannes.berg@intel.com>
Oliver Neukum e6380b
Date: Fri, 15 Jan 2021 13:05:58 +0200
Oliver Neukum e6380b
Subject: [PATCH] iwlwifi: pcie: reschedule in long-running memory reads
Oliver Neukum e6380b
Git-commit: 3d372c4edfd4dffb7dea71c6b096fb414782b776
Oliver Neukum e6380b
References: git-fixes
Oliver Neukum e6380b
Patch-mainline: v5.11-rc6
Oliver Neukum e6380b
Oliver Neukum e6380b
If we spin for a long time in memory reads that (for some reason in
Oliver Neukum e6380b
hardware) take a long time, then we'll eventually get messages such
Oliver Neukum e6380b
as
Oliver Neukum e6380b
Oliver Neukum e6380b
  watchdog: BUG: soft lockup - CPU#2 stuck for 24s! [kworker/2:2:272]
Oliver Neukum e6380b
Oliver Neukum e6380b
This is because the reading really does take a very long time, and
Oliver Neukum e6380b
we don't schedule, so we're hogging the CPU with this task, at least
Oliver Neukum e6380b
if CONFIG_PREEMPT is not set, e.g. with CONFIG_PREEMPT_VOLUNTARY=y.
Oliver Neukum e6380b
Oliver Neukum e6380b
Previously I misinterpreted the situation and thought that this was
Oliver Neukum e6380b
only going to happen if we had interrupts disabled, and then fixed
Oliver Neukum e6380b
this (which is good anyway, however), but that didn't always help;
Oliver Neukum e6380b
looking at it again now I realized that the spin unlock will only
Oliver Neukum e6380b
reschedule if CONFIG_PREEMPT is used.
Oliver Neukum e6380b
Oliver Neukum e6380b
In order to avoid this issue, change the code to cond_resched() if
Oliver Neukum e6380b
we've been spinning for too long here.
Oliver Neukum e6380b
Oliver Neukum e6380b
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Oliver Neukum e6380b
Fixes: 04516706bb99 ("iwlwifi: pcie: limit memory read spin time")
Oliver Neukum e6380b
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Oliver Neukum e6380b
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Oliver Neukum e6380b
Link: https://lore.kernel.org/r/iwlwifi.20210115130253.217a9d6a6a12.If964cb582ab0aaa94e81c4ff3b279eaafda0fd3f@changeid
Oliver Neukum e6380b
Signed-off-by: Oliver Neukum <oneukum@suse.com>
Oliver Neukum e6380b
---
Oliver Neukum e6380b
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c |    7 ++++++-
Oliver Neukum e6380b
 1 file changed, 6 insertions(+), 1 deletion(-)
Oliver Neukum e6380b
Oliver Neukum e6380b
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
Oliver Neukum e6380b
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
Oliver Neukum e6380b
@@ -2133,6 +2133,7 @@ static int iwl_trans_pcie_read_mem(struc
Oliver Neukum e6380b
 	u32 *vals = buf;
Oliver Neukum e6380b
 
Oliver Neukum e6380b
 	while (offs < dwords) {
Oliver Neukum e6380b
+		bool resched = false;
Oliver Neukum e6380b
 		/* limit the time we spin here under lock to 1/2s */
Oliver Neukum e6380b
 		ktime_t timeout = ktime_add_us(ktime_get(), 500 * USEC_PER_MSEC);
Oliver Neukum e6380b
 
Oliver Neukum e6380b
@@ -2149,10 +2150,14 @@ static int iwl_trans_pcie_read_mem(struc
Oliver Neukum e6380b
 				 * do it once in 128 reads
Oliver Neukum e6380b
 				 */
Oliver Neukum e6380b
 				if (offs % 128 == 0 && ktime_after(ktime_get(),
Oliver Neukum e6380b
-								   timeout))
Oliver Neukum e6380b
+								   timeout)) {
Oliver Neukum e6380b
+					resched = true;
Oliver Neukum e6380b
 					break;
Oliver Neukum e6380b
+				}
Oliver Neukum e6380b
 			}
Oliver Neukum e6380b
 			iwl_trans_release_nic_access(trans, &flags);
Oliver Neukum e6380b
+			if (resched)
Oliver Neukum e6380b
+				cond_resched();
Oliver Neukum e6380b
 		} else {
Oliver Neukum e6380b
 			return -EBUSY;
Oliver Neukum e6380b
 		}