summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-05-05 17:22:39 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-05-05 17:22:40 -0600
commit375fb2964fd726d47368d55a12a1ddd33f3b268c (patch)
tree4144efeebb520780e4de36d0e6462a744a2426ba /kernel
parente21bff20d36cf0fb5fbe62d02ade9ee0858bd8d5 (diff)
parent7fa8b4c857a2e0148b951e7a8547f74ed55a42ae (diff)
Promotion of kernel.lnx.4.4-160504.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 998828 I757329e68af439701b8f065c99a6a4b0c390cba2 msm: mdss: Add mdp capability to expose writeback interf 980569 I97ff3d53c12ed163ae5dbec184ed9445c901459e msm: ipa: Fix suspend bit clearing on disconnected pipe 954074 If98ef69e2474f1c50670c2605afe9769a4e0fb39 PFK: ice: change to non-atomic scm calls 1011902 Ie94ffce93d28d08610310885e4f257ebdbc15dd1 msm: vidc: Allow zero length qbuf 978768 I22696b17ec6ff11b1a378df9611eb8ab4be01358 msm: mdss: hdmi: update switch node on hpd off 1011445 I53bcd8293f7587ddba64ed0e019b77eee62b5e72 icnss: Enable SMMU BYPASS mode 993480 I61a48353428b3faa042fbc85e259b33c7f23bdb0 msm: kgsl: Remove harmless preemption log message 1011086 985182 I39d3d234222b6136ab0e68367e13c1276dce61f6 soc: qcom: rpm_master_stat: Add additional debug stats 1000506 Ie742148fe3b04677365a7247a89c2bed412e4d31 msm: ipa: Fix to update the descriptor length in SG scen 973565 If54caf008c654f488986a279bd19bea97457dc2c msm: kgsl: Disable ISENSE CGC 1003233 Ic36aaa86b7799c962a1128d16f0ec670698e8570 defconfig: arm64: msm: Enable IOMMU debug tracking 987074 Iae380e0f44dd53bee8ff4cec347a6b9a632b1f84 msm: kgsl: Don't spam kmsg due to invalid IOCTL requests 1005492 Ibc5ee5145dee3980ddca3d9922663eb96420d011 msm: ipa: odu: change IPC logging to common buffer 971156 Ibdf6fef6f3f700f3c5315c228c0473e47fb62163 msm: kgsl: Purge unused #defines 989004 Id5f244a57a2b991a10b603ef7236193d4282fd0f msm: kgsl: Remove superfluous NULL checks when reading t 1011110 I2000cab0a56a890cbd5503306a794e6b9b295db6 msm: camera: Correct hardware register settings for CSIP 1002547 Ifbecd46f8e3f8e93d846da3dfc72f7ef70687589 msm: cpp: Ignore input validation for sof freeze/unfreez 1007342 I904ee0b08079972b181f53fdc5a6022871da74e8 irqchip: irq-msm: Remove pinctrl_irq_dummy(..) hook 1005036 I8cd2403bed66141c99ccf8b9c57e59b936c1d90e clk: msm: clock-gcc-cobalt: Add clock reset support for 994283 I611155901e928fa8d9bbcbdf2511cd98aa36df2c ipa: Fix holb monitor response handling from Uc 1007342 I9016aadac88483c8547ed1a40cb6c55909f347cf irqchip: irq-msm: Delete irq-msm.c 1001217 1008552 Id326c73f78f3fadb5193a1e840f295d764fb013b msm: vidc: Set constrained intra refresh property 1010331 I50231b6c219e6a54379f6b94a23486a320ade09e ARM: dts: msm: update VDD_GFX CPR parameters for msmcoba 1010111 I7f254f579182effbc1f1a3d49c3c917d3c7af162 msm: thermal: Make boot-up mitigation optional 993738 Ie615ef440ab613f0b4f0601500188068440c29fe msm: camera: Avoid uninitialized variables 1009871 I57496aeb47d907f540a25c854ef7b35c6b5ab399 msm: jpeg: Expose JPEG DMA max downscale to user space 1007822 I23800a58459b0d9b15168cbef409374495e59ee1 edac: cortex: Update the CPU name 978768 I9556c6457258598e6b6758573bb0263d53e612da msm: mdss: hdmi: check for scrambler override 971174 Iaa113c8414a2d2d8f92b3cb21eaf2e422f273454 msm: kgsl: Add MMU offset mapping functions 1010111 If144319371a5c65f193ffac8fb9852a836125966 msm: thermal: Reorganize KTM probe function 1007266 Icb876f16cac9471c523f3ef5b5fd3ede9d5d597c msm: thermal: Prolong KTM mitigation till thermal-engine 1010111 Ica59aeb0c94581e3c37b5b7df16c187ced45c28a msm: thermal: Remove proactive vdd restriction during pr 1009268 I2d38454fce77a895f0aaf18e01f7d0c9f3c64692 regulator: cpr3-mmss-regulator: update reference voltage 1007459 Ic9dd60923198f38117843e9e087287fac294c197 defconfig: msmcortex: Enable workqueue watchdog 1010715 I2144bacc11190b92d14b00480dd538e27d13c3e1 ARM: dts: msm: Add qcom,msm-imem-diag-dload node on msmc 972831 I005041820e3721536693c892f5bc1d8d977dd770 defconfig: msm: sde: Add config for v4l2 sde rotator dri 1001770 I622fd971201b6c0001212a696c3d12aea409c11b Revert "spmi: pmic_arb: use handle_fasteoi_irq handler" 1010595 Ie1b74b6a3eac563ee34865655b046f71411aca65 AndroidKernel.mk: Enforce KERNEL_OBJ generation 1000754 If66039ff752741e44b00175a7cc73681e7ca16ae Revert "ARM: dts: msm: disable UFS LPM modes for msmcoba 986130 I552094c64bd9fb360ddd73022fe21a403c245b2f msm_11ad: keep rf_clk3 on during wil6210 activity 1006743 I9b565a34e2068bf575974eaf3dc9f7820bdd7a96 mm/page_owner: ask users about default setting of PAGE_O 992317 I43e08ccefbf2d3911191b2aad5168979956e1626 msm: kgsl: Dump 64KB of preemption record in snapshot 1011086 Ie5c9236ad34ea61a375a4a3ae1f1d91fda0a9ccf drivers: soc: qcom: rpm_stats: Switch to use arch_counte 994759 Ib3006067e184bf97adf75971ab96b2c673909eba ARM: dts: msm: Set the high bank bit value for MSMcobalt 1006743 I35602327d75945c35126ce2d657803d786a44121 defconfig: msmcortex: Enable PAGE_OWNER and DEBUG_PAGEAL 1009871 Idb3780f0ce3d8c0b3f659aee2c0806b20c7f1379 ARM: dts: msm: Add JPEG DMA max downscale node for msmco 1002205 I789cdec6f056b17a605f3454e6cd5702542c454f msm: ipa: Fix to accessing ipa_q6_clnt handle 1009142 Idae5097ee0247589885328c9e55b65f981a261c2 ARM: dts: msm: update VDD_APC CPR settings for msmcobalt 999965 I2d7d74e48ce80aa18cab2d42191db8d5edb4a076 msm: ipa: Fix to release IPA clock during ap suspend 1009142 I6a6cb1096cc91ac995dbc36c8edaaa20c392e6c8 ARM: dts: msm: enable VDD_APC CPR HW closed-loop operati 984991 Id5a5128edb379308fa91b53062b6773af1b6de18 msm: ipa: Fix to QMI initialization and polling state 1008505 Ie3d3889cc6c35011f239468ddf465c553a6b1c97 msm: mdss: Skip setting up Qseed3 for non-vig pipes 1003233 I65e7fe7d8f94ba3ac6a3d9030f15fd5a0b97c188 ARM: dts: msm: Add IOMMU test device nodes for 8996 and 1010715 I076928436a8b1b4d1c3ee7e48db9b3314ec1fc05 usb: gadget: f_diag: Update serial_number with dload_coo 1007344 I0bf7b33c3584f3d6cf5ef58dfe72be46212041da lib: memtest: Add MEMTEST_ENABLE_DEFAULT option 1011110 Ieee68a709a1f56d53bd2746fa28fbd76195270b0 ARM: dts: msm: Correct camera nodes for msmcobalt 1000756 I2d2e651ba554812198d721892e14ca1a61a34027 ARM: dts: msm: setup external clock sources for DSI cloc 1009142 I6af5a0bd5ddb5fdb22585f9da34524475f49233f regulator: cprh-kbss-regulator: update corner switch del 1007459 Id7dfbbd2701128a942b1bcac2299e07a66db8657 workqueue: implement lockup detector 978768 Ib48c02b2b89f7fdb347afd3a02d8b6b7c1c03e85 msm: mdss: hdmi: refactor event handler 971172 If426fb7599be0a79b6f37b8008a2310b1c006e93 msm: kgsl: Clean up adreno trace code 1007351 Iff58832a535227ea071ce5b14d537d9993f9dfc2 lib: Makefile: Ignore Kasan errors reported from the fin 1011086 Ibceaa8f948e203c39e3df55b135c0a394f39ca5f qcom: Port rpm logs and stats driver from 3.18 to 4.4 ke 1007809 I4b68c0e658316b2958d8c9536c3e80e01faf55a4 ARM: dts: msm: Venus PIL clock voting update for MSMCOBA 1010331 Id4beb16d0324ec9c3d62d6d1ead664e215acaaf1 ARM: dts: msm: enable VDD_GFX closed-loop CPR for msmcob 1008505 Icc6ee5e2ba60d7f619393518b4f06aee6f784f3d msm: mdss: update bus scaling macro 1005492 I31acc2008800d213cc69003f9781fee04b5935aa msm: ipa3: mhi: add IPC logging to common buffer 1005492 I69f3536e297eae8453370b44f66ec0f520f16cd5 msm: ipa3: rmnet_ipa: add IPC logging to common buffer 1003233 I6a5802aff5bab99d29c6ed9d953a203cbd8015bb iommu/iommu-debug: Add dummy driver for standalone testi 999530 Iddb5e882e1324e0382359109b86ebcaa26b3d851 defconfig: arm64: msm: enable service notifier and locat 1009865 I70db6555d236857c5a8d62a337afdc9fec22c97f icnss: Add SMMU support 991396 Idb248e1270b79b51e53de687793030a047fe6c73 msm: ipa: Fix memory free issue 971398 Id1e3e0f756ac1c9a0ff4f4e6ce073e80e31473b8 msm: kgsl: Check for failure in coresight initialization 977862 Icac7fb4355ee1fd07e7127ea5c2721665e279272 msm: kgsl: Use a page pool to reduce allocation time 1009471 If11cd577d30c22d79544f4668e08ccf269237236 net: ipc_router: Fail to send resume_tx for local commun 988861 Ifc3ec45297c2a29ad6f7d70dd0bd59238ac8cc3d msm: kgsl: Fix overflow in sharedmem read/write function 978768 Ia305e1eb5d3da1dfbf868650e5ee84018255476b msm: mdss: hdmi: add dynamic fps support 1009810 Ief99a7af7e3f8147469b1b5a68da973ab26a988b ARM: dts: msm: Remove the duplicated RTB dt entry 989231 I2cec6c6f9fe7aea0e2276b01133f8c3505b9919f msm: ipa3: Move IPA headers building to IPAHAL 1010329 I01210f48d32d7d6cb32f4977e52fb46acd33b1ba clk: msm: clock-gcc-cobalt: Add SVS2 frequencies for som 1007515 Iae73d82f6797b8d0628a3f5a31a916d0a43206df defconfig: msm: Enable config parameter for regulatory d 978768 I5b73d3b558af576b5114c42b63260bb688f2d8d1 msm: mdss: hdmi: refactor initialization of features 1007459 I6fe77926acd4240458cab29d399f81d8739a16c0 watchdog: introduce touch_softlockup_watchdog_sched() 1006609 I17d4cc0a38770f0c5067fa8047cd63e7bf085e48 ASoC: msm: audio-effects: misc fixes in h/w accelerated 978768 I52b11f19f576e13e197e8c576a9c5ada54416f5e msm: mdss: fb: reconfigure panel if output format has ch Change-Id: Ida9a27fac0393dff4104005d722604014da57d7b CRs-Fixed: 1009871, 986130, 1000756, 1000506, 1000754, 1009142, 1010329, 1005492, 971172, 999965, 1007344, 973565, 1001770, 992317, 1007342, 994283, 1010111, 987074, 984991, 1007266, 1002205, 1001217, 985182, 1007515, 1009810, 1006609, 1006743, 999530, 993480, 1008505, 993738, 972831, 978768, 971174, 1005036, 1007822, 1010595, 954074, 977862, 1011086, 1007809, 1003233, 1010715, 1009865, 1007459, 1011445, 1011110, 980569, 994759, 1010331, 989004, 1007351, 971398, 1009471, 989231, 988861, 1008552, 1011902, 971156, 1009268, 998828, 991396, 1002547
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/clock.c2
-rw-r--r--kernel/time/tick-sched.c6
-rw-r--r--kernel/watchdog.c18
-rw-r--r--kernel/workqueue.c174
4 files changed, 192 insertions, 8 deletions
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c
index caf4041f5b0a..bc54e84675da 100644
--- a/kernel/sched/clock.c
+++ b/kernel/sched/clock.c
@@ -354,7 +354,7 @@ void sched_clock_idle_wakeup_event(u64 delta_ns)
return;
sched_clock_tick();
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
}
EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 89dcc6cafa07..7f0f1d8d46b0 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -163,7 +163,7 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
* when we go busy again does not account too much ticks.
*/
if (ts->tick_stopped) {
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
if (is_idle_task(current))
ts->idle_jiffies++;
}
@@ -450,7 +450,7 @@ static void tick_nohz_update_jiffies(ktime_t now)
tick_do_update_jiffies64(now);
local_irq_restore(flags);
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
}
/*
@@ -721,7 +721,7 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
update_cpu_load_nohz();
calc_load_exit_idle();
- touch_softlockup_watchdog();
+ touch_softlockup_watchdog_sched();
/*
* Cancel the scheduled timer and restore the tick
*/
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index d12d5b86a555..b40f7f35413d 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -20,6 +20,7 @@
#include <linux/smpboot.h>
#include <linux/sched/rt.h>
#include <linux/tick.h>
+#include <linux/workqueue.h>
#include <asm/irq_regs.h>
#include <linux/kvm_para.h>
@@ -232,7 +233,15 @@ static void __touch_watchdog(void)
__this_cpu_write(watchdog_touch_ts, get_timestamp());
}
-void touch_softlockup_watchdog(void)
+/**
+ * touch_softlockup_watchdog_sched - touch watchdog on scheduler stalls
+ *
+ * Call when the scheduler may have stalled for legitimate reasons
+ * preventing the watchdog task from executing - e.g. the scheduler
+ * entering idle state. This should only be used for scheduler events.
+ * Use touch_softlockup_watchdog() for everything else.
+ */
+void touch_softlockup_watchdog_sched(void)
{
/*
* Preemption can be enabled. It doesn't matter which CPU's timestamp
@@ -240,6 +249,12 @@ void touch_softlockup_watchdog(void)
*/
raw_cpu_write(watchdog_touch_ts, 0);
}
+
+void touch_softlockup_watchdog(void)
+{
+ touch_softlockup_watchdog_sched();
+ wq_watchdog_touch(raw_smp_processor_id());
+}
EXPORT_SYMBOL(touch_softlockup_watchdog);
void touch_all_softlockup_watchdogs(void)
@@ -253,6 +268,7 @@ void touch_all_softlockup_watchdogs(void)
*/
for_each_watchdog_cpu(cpu)
per_cpu(watchdog_touch_ts, cpu) = 0;
+ wq_watchdog_touch(-1);
}
#ifdef CONFIG_HARDLOCKUP_DETECTOR
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 15dacf9590cb..58fe79122a61 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -149,6 +149,8 @@ struct worker_pool {
int id; /* I: pool ID */
unsigned int flags; /* X: flags */
+ unsigned long watchdog_ts; /* L: watchdog timestamp */
+
struct list_head worklist; /* L: list of pending works */
int nr_workers; /* L: total number of workers */
@@ -1084,6 +1086,8 @@ static void pwq_activate_delayed_work(struct work_struct *work)
struct pool_workqueue *pwq = get_work_pwq(work);
trace_workqueue_activate_work(work);
+ if (list_empty(&pwq->pool->worklist))
+ pwq->pool->watchdog_ts = jiffies;
move_linked_works(work, &pwq->pool->worklist, NULL);
__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
pwq->nr_active++;
@@ -1386,6 +1390,8 @@ retry:
trace_workqueue_activate_work(work);
pwq->nr_active++;
worklist = &pwq->pool->worklist;
+ if (list_empty(worklist))
+ pwq->pool->watchdog_ts = jiffies;
} else {
work_flags |= WORK_STRUCT_DELAYED;
worklist = &pwq->delayed_works;
@@ -2159,6 +2165,8 @@ recheck:
list_first_entry(&pool->worklist,
struct work_struct, entry);
+ pool->watchdog_ts = jiffies;
+
if (likely(!(*work_data_bits(work) & WORK_STRUCT_LINKED))) {
/* optimization path, not strictly necessary */
process_one_work(worker, work);
@@ -2242,6 +2250,7 @@ repeat:
struct pool_workqueue, mayday_node);
struct worker_pool *pool = pwq->pool;
struct work_struct *work, *n;
+ bool first = true;
__set_current_state(TASK_RUNNING);
list_del_init(&pwq->mayday_node);
@@ -2258,9 +2267,14 @@ repeat:
* process'em.
*/
WARN_ON_ONCE(!list_empty(scheduled));
- list_for_each_entry_safe(work, n, &pool->worklist, entry)
- if (get_work_pwq(work) == pwq)
+ list_for_each_entry_safe(work, n, &pool->worklist, entry) {
+ if (get_work_pwq(work) == pwq) {
+ if (first)
+ pool->watchdog_ts = jiffies;
move_linked_works(work, scheduled, &n);
+ }
+ first = false;
+ }
if (!list_empty(scheduled)) {
process_scheduled_works(rescuer);
@@ -3071,6 +3085,7 @@ static int init_worker_pool(struct worker_pool *pool)
pool->cpu = -1;
pool->node = NUMA_NO_NODE;
pool->flags |= POOL_DISASSOCIATED;
+ pool->watchdog_ts = jiffies;
INIT_LIST_HEAD(&pool->worklist);
INIT_LIST_HEAD(&pool->idle_list);
hash_init(pool->busy_hash);
@@ -4310,7 +4325,9 @@ void show_workqueue_state(void)
pr_info("pool %d:", pool->id);
pr_cont_pool_info(pool);
- pr_cont(" workers=%d", pool->nr_workers);
+ pr_cont(" hung=%us workers=%d",
+ jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000,
+ pool->nr_workers);
if (pool->manager)
pr_cont(" manager: %d",
task_pid_nr(pool->manager->task));
@@ -5169,6 +5186,154 @@ static void workqueue_sysfs_unregister(struct workqueue_struct *wq)
static void workqueue_sysfs_unregister(struct workqueue_struct *wq) { }
#endif /* CONFIG_SYSFS */
+/*
+ * Workqueue watchdog.
+ *
+ * Stall may be caused by various bugs - missing WQ_MEM_RECLAIM, illegal
+ * flush dependency, a concurrency managed work item which stays RUNNING
+ * indefinitely. Workqueue stalls can be very difficult to debug as the
+ * usual warning mechanisms don't trigger and internal workqueue state is
+ * largely opaque.
+ *
+ * Workqueue watchdog monitors all worker pools periodically and dumps
+ * state if some pools failed to make forward progress for a while where
+ * forward progress is defined as the first item on ->worklist changing.
+ *
+ * This mechanism is controlled through the kernel parameter
+ * "workqueue.watchdog_thresh" which can be updated at runtime through the
+ * corresponding sysfs parameter file.
+ */
+#ifdef CONFIG_WQ_WATCHDOG
+
+static void wq_watchdog_timer_fn(unsigned long data);
+
+static unsigned long wq_watchdog_thresh = 30;
+static struct timer_list wq_watchdog_timer =
+ TIMER_DEFERRED_INITIALIZER(wq_watchdog_timer_fn, 0, 0);
+
+static unsigned long wq_watchdog_touched = INITIAL_JIFFIES;
+static DEFINE_PER_CPU(unsigned long, wq_watchdog_touched_cpu) = INITIAL_JIFFIES;
+
+static void wq_watchdog_reset_touched(void)
+{
+ int cpu;
+
+ wq_watchdog_touched = jiffies;
+ for_each_possible_cpu(cpu)
+ per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;
+}
+
+static void wq_watchdog_timer_fn(unsigned long data)
+{
+ unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
+ bool lockup_detected = false;
+ struct worker_pool *pool;
+ int pi;
+
+ if (!thresh)
+ return;
+
+ rcu_read_lock();
+
+ for_each_pool(pool, pi) {
+ unsigned long pool_ts, touched, ts;
+
+ if (list_empty(&pool->worklist))
+ continue;
+
+ /* get the latest of pool and touched timestamps */
+ pool_ts = READ_ONCE(pool->watchdog_ts);
+ touched = READ_ONCE(wq_watchdog_touched);
+
+ if (time_after(pool_ts, touched))
+ ts = pool_ts;
+ else
+ ts = touched;
+
+ if (pool->cpu >= 0) {
+ unsigned long cpu_touched =
+ READ_ONCE(per_cpu(wq_watchdog_touched_cpu,
+ pool->cpu));
+ if (time_after(cpu_touched, ts))
+ ts = cpu_touched;
+ }
+
+ /* did we stall? */
+ if (time_after(jiffies, ts + thresh)) {
+ lockup_detected = true;
+ pr_emerg("BUG: workqueue lockup - pool");
+ pr_cont_pool_info(pool);
+ pr_cont(" stuck for %us!\n",
+ jiffies_to_msecs(jiffies - pool_ts) / 1000);
+ }
+ }
+
+ rcu_read_unlock();
+
+ if (lockup_detected)
+ show_workqueue_state();
+
+ wq_watchdog_reset_touched();
+ mod_timer(&wq_watchdog_timer, jiffies + thresh);
+}
+
+void wq_watchdog_touch(int cpu)
+{
+ if (cpu >= 0)
+ per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies;
+ else
+ wq_watchdog_touched = jiffies;
+}
+
+static void wq_watchdog_set_thresh(unsigned long thresh)
+{
+ wq_watchdog_thresh = 0;
+ del_timer_sync(&wq_watchdog_timer);
+
+ if (thresh) {
+ wq_watchdog_thresh = thresh;
+ wq_watchdog_reset_touched();
+ mod_timer(&wq_watchdog_timer, jiffies + thresh * HZ);
+ }
+}
+
+static int wq_watchdog_param_set_thresh(const char *val,
+ const struct kernel_param *kp)
+{
+ unsigned long thresh;
+ int ret;
+
+ ret = kstrtoul(val, 0, &thresh);
+ if (ret)
+ return ret;
+
+ if (system_wq)
+ wq_watchdog_set_thresh(thresh);
+ else
+ wq_watchdog_thresh = thresh;
+
+ return 0;
+}
+
+static const struct kernel_param_ops wq_watchdog_thresh_ops = {
+ .set = wq_watchdog_param_set_thresh,
+ .get = param_get_ulong,
+};
+
+module_param_cb(watchdog_thresh, &wq_watchdog_thresh_ops, &wq_watchdog_thresh,
+ 0644);
+
+static void wq_watchdog_init(void)
+{
+ wq_watchdog_set_thresh(wq_watchdog_thresh);
+}
+
+#else /* CONFIG_WQ_WATCHDOG */
+
+static inline void wq_watchdog_init(void) { }
+
+#endif /* CONFIG_WQ_WATCHDOG */
+
static void __init wq_numa_init(void)
{
cpumask_var_t *tbl;
@@ -5292,6 +5457,9 @@ static int __init init_workqueues(void)
!system_unbound_wq || !system_freezable_wq ||
!system_power_efficient_wq ||
!system_freezable_power_efficient_wq);
+
+ wq_watchdog_init();
+
return 0;
}
early_initcall(init_workqueues);