@@ -47,6 +47,7 @@ static DEFINE_XARRAY_ALLOC(cid_xarray);
4747#define REQUEST_HEARTBEAT_TIMEOUT (msecs_to_jiffies(500)) /* 0.5 seconds */
4848#define HEARTBEAT_REQUEST_INTERVAL (5000)
4949#define LOGGING_SLEEP_INTERVAL (500)
50+ #define AMC_STOP_POLL_INTERVAL_MS (50)
5051
5152
5253/* AMC Identify Command Version Major and Minor Numbers */
@@ -956,6 +957,32 @@ void release_amc(struct amc_control_ctxt **amc_ctrl_ctxt)
956957 *
957958 * Return: the errno return code if thread exits
958959 */
960+
961+ /**
962+ * amc_sleep_or_stop() - Sleep up to @msecs, returning early the moment a stop is
963+ * requested.
964+ * Unlike a bare msleep() (uninterruptible, so kthread_stop() must wait out the whole interval),
965+ * this polls kthread_should_stop() every AMC_STOP_POLL_INTERVAL_MS, so teardown and rmmod is prompt.
966+ * @msecs: maximum time to sleep, in milliseconds.
967+ *
968+ * Return: true if a stop was requested (caller should break its loop), else false.
969+ */
970+ static bool amc_sleep_or_stop (unsigned int msecs )
971+ {
972+ // Only return on timeout once the full interval has elapsed.
973+ // the sleep sets the thread's polling cadence, so cutting it short would busy-loop the GCQ mailbox.
974+ unsigned long deadline = jiffies + msecs_to_jiffies (msecs );
975+
976+ while (!kthread_should_stop ()) {
977+ // have we slept long enough?
978+ if (time_after_eq (jiffies , deadline ))
979+ return false;
980+ msleep (AMC_STOP_POLL_INTERVAL_MS ); // sleeping by small chunks to quit early
981+ }
982+
983+ return true;
984+ }
985+
959986static int heartbeat_health_thread (void * data )
960987{
961988 struct amc_control_ctxt * amc_ctxt = NULL ;
@@ -1019,10 +1046,8 @@ static int heartbeat_health_thread(void *data)
10191046 }
10201047 }
10211048
1022- msleep (HEARTBEAT_REQUEST_INTERVAL );
1023-
10241049 /* only exit from the thread is within the unset_amc context */
1025- if (kthread_should_stop ( ))
1050+ if (amc_sleep_or_stop ( HEARTBEAT_REQUEST_INTERVAL ))
10261051 break ;
10271052 }
10281053 return 0 ;
@@ -1065,10 +1090,8 @@ static int logging_thread(void *data)
10651090 while (1 ) {
10661091 if (logging_failed == false)
10671092 dump_amc_log (amc_ctxt );
1068- msleep (LOGGING_SLEEP_INTERVAL );
1069-
10701093 /* only exit from the thread is within the unset_amc context */
1071- if (kthread_should_stop ( ))
1094+ if (amc_sleep_or_stop ( LOGGING_SLEEP_INTERVAL ))
10721095 break ;
10731096 }
10741097 return 0 ;
0 commit comments