From: Sasha Levin Date: Fri, 7 Feb 2020 16:10:36 +0000 (-0500) Subject: fixes for 5.4 X-Git-Tag: v4.19.103~86 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ca2ecdabe8384a8aeb274c0d20d6a726f5f6c471;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/asoc-sof-core-release-resources-on-errors-in-probe_c.patch b/queue-5.4/asoc-sof-core-release-resources-on-errors-in-probe_c.patch new file mode 100644 index 00000000000..8e2e29ed3cb --- /dev/null +++ b/queue-5.4/asoc-sof-core-release-resources-on-errors-in-probe_c.patch @@ -0,0 +1,120 @@ +From 89f645b6ec6a76dc6108f41720b047ef698ca4ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2020 15:36:21 -0600 +Subject: ASoC: SOF: core: release resources on errors in probe_continue + +From: Pierre-Louis Bossart + +[ Upstream commit 410e5e55c9c1c9c0d452ac5b9adb37b933a7747e ] + +The initial intent of releasing resources in the .remove does not work +well with HDaudio codecs. If the probe_continue() fails in a work +queue, e.g. due to missing firmware or authentication issues, we don't +release any resources, and as a result the kernel oopses during +suspend operations. + +The suggested fix is to release all resources during errors in +probe_continue(), and use fw_state to track resource allocation +state, so that .remove does not attempt to release the same +hardware resources twice. PM operations are also modified so that +no action is done if DSP resources have been freed due to +an error at probe. + +Reported-by: Takashi Iwai +Co-developed-by: Kai Vehmanen +Signed-off-by: Kai Vehmanen +Bugzilla: http://bugzilla.suse.com/show_bug.cgi?id=1161246 +Signed-off-by: Pierre-Louis Bossart +Reviewed-by: Takashi Iwai +Link: https://lore.kernel.org/r/20200124213625.30186-4-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + sound/soc/sof/core.c | 32 +++++++++++--------------------- + sound/soc/sof/pm.c | 4 ++++ + 2 files changed, 15 insertions(+), 21 deletions(-) + +diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c +index f9ebdf2cfc31d..12aec140819a2 100644 +--- a/sound/soc/sof/core.c ++++ b/sound/soc/sof/core.c +@@ -440,7 +440,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) + + return 0; + +-#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) + fw_trace_err: + snd_sof_free_trace(sdev); + fw_run_err: +@@ -451,22 +450,10 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) + snd_sof_free_debug(sdev); + dbg_err: + snd_sof_remove(sdev); +-#else +- +- /* +- * when the probe_continue is handled in a work queue, the +- * probe does not fail so we don't release resources here. +- * They will be released with an explicit call to +- * snd_sof_device_remove() when the PCI/ACPI device is removed +- */ +- +-fw_trace_err: +-fw_run_err: +-fw_load_err: +-ipc_err: +-dbg_err: + +-#endif ++ /* all resources freed, update state to match */ ++ sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; ++ sdev->first_boot = true; + + return ret; + } +@@ -545,10 +532,12 @@ int snd_sof_device_remove(struct device *dev) + if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) + cancel_work_sync(&sdev->probe_work); + +- snd_sof_fw_unload(sdev); +- snd_sof_ipc_free(sdev); +- snd_sof_free_debug(sdev); +- snd_sof_free_trace(sdev); ++ if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) { ++ snd_sof_fw_unload(sdev); ++ snd_sof_ipc_free(sdev); ++ snd_sof_free_debug(sdev); ++ snd_sof_free_trace(sdev); ++ } + + /* + * Unregister machine driver. This will unbind the snd_card which +@@ -564,7 +553,8 @@ int snd_sof_device_remove(struct device *dev) + * scheduled on, when they are unloaded. Therefore, the DSP must be + * removed only after the topology has been unloaded. + */ +- snd_sof_remove(sdev); ++ if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) ++ snd_sof_remove(sdev); + + /* release firmware */ + release_firmware(pdata->fw); +diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c +index e9fbac38d9238..195af259e78e3 100644 +--- a/sound/soc/sof/pm.c ++++ b/sound/soc/sof/pm.c +@@ -269,6 +269,10 @@ static int sof_resume(struct device *dev, bool runtime_resume) + if (!sof_ops(sdev)->resume || !sof_ops(sdev)->runtime_resume) + return 0; + ++ /* DSP was never successfully started, nothing to resume */ ++ if (sdev->first_boot) ++ return 0; ++ + /* + * if the runtime_resume flag is set, call the runtime_resume routine + * or else call the system resume routine +-- +2.20.1 + diff --git a/queue-5.4/asoc-sof-introduce-state-machine-for-fw-boot.patch b/queue-5.4/asoc-sof-introduce-state-machine-for-fw-boot.patch new file mode 100644 index 00000000000..9f42c62f1fa --- /dev/null +++ b/queue-5.4/asoc-sof-introduce-state-machine-for-fw-boot.patch @@ -0,0 +1,328 @@ +From 1b12b51278e493b275c5038b0d0d1fbbaf3d6646 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2019 18:26:09 -0600 +Subject: ASoC: SOF: Introduce state machine for FW boot + +From: Ranjani Sridharan + +[ Upstream commit 6ca5cecbd1c1758666ab79446f19e0e61ed11444 ] + +Add a state machine for FW boot to track the +different stages of FW boot and replace the boot_complete +field with fw_state field in struct snd_sof_dev. +This will be used to determine the actions to be performed +during system suspend. + +One of the main motivations for adding this change is the +fact that errors during the top-level SOF device probe cannot +be propagated and therefore suspending the SOF device normally +during system suspend could potentially run into errors. +For example, with the current flow, if the FW boot failed +for some reason and the system suspends, the SOF device +suspend could fail because the CTX_SAVE IPC would be attempted +even though the FW never really booted successfully causing it +to time out. Another scenario that the state machine fixes +is when the runtime suspend for the SOF device fails and +the DSP is powered down nevertheless, the CTX_SAVE IPC during +system suspend would timeout because the DSP is already +powered down. + +Reviewed-by: Curtis Malainey +Reviewed-by: Daniel Baluta +Signed-off-by: Ranjani Sridharan +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20191218002616.7652-2-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sof/core.c | 50 +++++++++++++++++++++++++++++++- + sound/soc/sof/intel/hda-loader.c | 1 - + sound/soc/sof/intel/hda.c | 4 +-- + sound/soc/sof/ipc.c | 17 ++++------- + sound/soc/sof/loader.c | 19 ++++++++---- + sound/soc/sof/pm.c | 21 +++++++++++++- + sound/soc/sof/sof-priv.h | 11 ++++++- + 7 files changed, 99 insertions(+), 24 deletions(-) + +diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c +index 075b80698477e..f9ebdf2cfc31d 100644 +--- a/sound/soc/sof/core.c ++++ b/sound/soc/sof/core.c +@@ -288,6 +288,46 @@ static int sof_machine_check(struct snd_sof_dev *sdev) + #endif + } + ++/* ++ * FW Boot State Transition Diagram ++ * ++ * +-----------------------------------------------------------------------+ ++ * | | ++ * ------------------ ------------------ | ++ * | | | | | ++ * | BOOT_FAILED | | READY_FAILED |-------------------------+ | ++ * | | | | | | ++ * ------------------ ------------------ | | ++ * ^ ^ | | ++ * | | | | ++ * (FW Boot Timeout) (FW_READY FAIL) | | ++ * | | | | ++ * | | | | ++ * ------------------ | ------------------ | | ++ * | | | | | | | ++ * | IN_PROGRESS |---------------+------------->| COMPLETE | | | ++ * | | (FW Boot OK) (FW_READY OK) | | | | ++ * ------------------ ------------------ | | ++ * ^ | | | ++ * | | | | ++ * (FW Loading OK) (System Suspend/Runtime Suspend) ++ * | | | | ++ * | | | | ++ * ------------------ ------------------ | | | ++ * | | | |<-----+ | | ++ * | PREPARE | | NOT_STARTED |<---------------------+ | ++ * | | | |<---------------------------+ ++ * ------------------ ------------------ ++ * | ^ | ^ ++ * | | | | ++ * | +-----------------------+ | ++ * | (DSP Probe OK) | ++ * | | ++ * | | ++ * +------------------------------------+ ++ * (System Suspend/Runtime Suspend) ++ */ ++ + static int sof_probe_continue(struct snd_sof_dev *sdev) + { + struct snd_sof_pdata *plat_data = sdev->pdata; +@@ -303,6 +343,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) + return ret; + } + ++ sdev->fw_state = SOF_FW_BOOT_PREPARE; ++ + /* check machine info */ + ret = sof_machine_check(sdev); + if (ret < 0) { +@@ -342,7 +384,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) + goto fw_load_err; + } + +- /* boot the firmware */ ++ sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; ++ ++ /* ++ * Boot the firmware. The FW boot status will be modified ++ * in snd_sof_run_firmware() depending on the outcome. ++ */ + ret = snd_sof_run_firmware(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to boot DSP firmware %d\n", +@@ -450,6 +497,7 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) + + sdev->pdata = plat_data; + sdev->first_boot = true; ++ sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; + dev_set_drvdata(dev, sdev); + + /* check all mandatory ops */ +diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c +index 65c2af3fcaab7..356bb134ae93a 100644 +--- a/sound/soc/sof/intel/hda-loader.c ++++ b/sound/soc/sof/intel/hda-loader.c +@@ -278,7 +278,6 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) + + /* init for booting wait */ + init_waitqueue_head(&sdev->boot_wait); +- sdev->boot_complete = false; + + /* prepare DMA for code loader stream */ + tag = cl_stream_prepare(sdev, 0x40, stripped_firmware.size, +diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c +index 5a5163eef2ef4..3c4b604412f0e 100644 +--- a/sound/soc/sof/intel/hda.c ++++ b/sound/soc/sof/intel/hda.c +@@ -166,7 +166,7 @@ void hda_dsp_dump_skl(struct snd_sof_dev *sdev, u32 flags) + panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, + HDA_ADSP_ERROR_CODE_SKL + 0x4); + +- if (sdev->boot_complete) { ++ if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) { + hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, + HDA_DSP_STACK_DUMP_SIZE); + snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, +@@ -193,7 +193,7 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) + HDA_DSP_SRAM_REG_FW_STATUS); + panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP); + +- if (sdev->boot_complete) { ++ if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) { + hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, + HDA_DSP_STACK_DUMP_SIZE); + snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, +diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c +index 7b6d69783e16a..8984d965037de 100644 +--- a/sound/soc/sof/ipc.c ++++ b/sound/soc/sof/ipc.c +@@ -348,19 +348,12 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev) + break; + case SOF_IPC_FW_READY: + /* check for FW boot completion */ +- if (!sdev->boot_complete) { ++ if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS) { + err = sof_ops(sdev)->fw_ready(sdev, cmd); +- if (err < 0) { +- /* +- * this indicates a mismatch in ABI +- * between the driver and fw +- */ +- dev_err(sdev->dev, "error: ABI mismatch %d\n", +- err); +- } else { +- /* firmware boot completed OK */ +- sdev->boot_complete = true; +- } ++ if (err < 0) ++ sdev->fw_state = SOF_FW_BOOT_READY_FAILED; ++ else ++ sdev->fw_state = SOF_FW_BOOT_COMPLETE; + + /* wake up firmware loader */ + wake_up(&sdev->boot_wait); +diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c +index a041adf0669de..ce114df5e4fce 100644 +--- a/sound/soc/sof/loader.c ++++ b/sound/soc/sof/loader.c +@@ -511,7 +511,6 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) + int init_core_mask; + + init_waitqueue_head(&sdev->boot_wait); +- sdev->boot_complete = false; + + /* create read-only fw_version debugfs to store boot version info */ + if (sdev->first_boot) { +@@ -543,19 +542,27 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev) + + init_core_mask = ret; + +- /* now wait for the DSP to boot */ +- ret = wait_event_timeout(sdev->boot_wait, sdev->boot_complete, ++ /* ++ * now wait for the DSP to boot. There are 3 possible outcomes: ++ * 1. Boot wait times out indicating FW boot failure. ++ * 2. FW boots successfully and fw_ready op succeeds. ++ * 3. FW boots but fw_ready op fails. ++ */ ++ ret = wait_event_timeout(sdev->boot_wait, ++ sdev->fw_state > SOF_FW_BOOT_IN_PROGRESS, + msecs_to_jiffies(sdev->boot_timeout)); + if (ret == 0) { + dev_err(sdev->dev, "error: firmware boot failure\n"); + snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX | + SOF_DBG_TEXT | SOF_DBG_PCI); +- /* after this point FW_READY msg should be ignored */ +- sdev->boot_complete = true; ++ sdev->fw_state = SOF_FW_BOOT_FAILED; + return -EIO; + } + +- dev_info(sdev->dev, "firmware boot complete\n"); ++ if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) ++ dev_info(sdev->dev, "firmware boot complete\n"); ++ else ++ return -EIO; /* FW boots but fw_ready op failed */ + + /* perform post fw run operations */ + ret = snd_sof_dsp_post_fw_run(sdev); +diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c +index e23beaeefe005..e9fbac38d9238 100644 +--- a/sound/soc/sof/pm.c ++++ b/sound/soc/sof/pm.c +@@ -283,6 +283,8 @@ static int sof_resume(struct device *dev, bool runtime_resume) + return ret; + } + ++ sdev->fw_state = SOF_FW_BOOT_PREPARE; ++ + /* load the firmware */ + ret = snd_sof_load_firmware(sdev); + if (ret < 0) { +@@ -292,7 +294,12 @@ static int sof_resume(struct device *dev, bool runtime_resume) + return ret; + } + +- /* boot the firmware */ ++ sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; ++ ++ /* ++ * Boot the firmware. The FW boot status will be modified ++ * in snd_sof_run_firmware() depending on the outcome. ++ */ + ret = snd_sof_run_firmware(sdev); + if (ret < 0) { + dev_err(sdev->dev, +@@ -338,6 +345,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) + if (!sof_ops(sdev)->suspend) + return 0; + ++ if (sdev->fw_state != SOF_FW_BOOT_COMPLETE) ++ goto power_down; ++ + /* release trace */ + snd_sof_release_trace(sdev); + +@@ -375,6 +385,12 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) + ret); + } + ++power_down: ++ ++ /* return if the DSP was not probed successfully */ ++ if (sdev->fw_state == SOF_FW_BOOT_NOT_STARTED) ++ return 0; ++ + /* power down all DSP cores */ + if (runtime_suspend) + ret = snd_sof_dsp_runtime_suspend(sdev); +@@ -385,6 +401,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) + "error: failed to power down DSP during suspend %d\n", + ret); + ++ /* reset FW state */ ++ sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; ++ + return ret; + } + +diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h +index 730f3259dd027..7b329bd99674f 100644 +--- a/sound/soc/sof/sof-priv.h ++++ b/sound/soc/sof/sof-priv.h +@@ -356,6 +356,15 @@ struct snd_sof_dai { + struct list_head list; /* list in sdev dai list */ + }; + ++enum snd_sof_fw_state { ++ SOF_FW_BOOT_NOT_STARTED = 0, ++ SOF_FW_BOOT_PREPARE, ++ SOF_FW_BOOT_IN_PROGRESS, ++ SOF_FW_BOOT_FAILED, ++ SOF_FW_BOOT_READY_FAILED, /* firmware booted but fw_ready op failed */ ++ SOF_FW_BOOT_COMPLETE, ++}; ++ + /* + * SOF Device Level. + */ +@@ -372,7 +381,7 @@ struct snd_sof_dev { + + /* DSP firmware boot */ + wait_queue_head_t boot_wait; +- u32 boot_complete; ++ enum snd_sof_fw_state fw_state; + u32 first_boot; + + /* work queue in case the probe is implemented in two steps */ +-- +2.20.1 + diff --git a/queue-5.4/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch b/queue-5.4/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch new file mode 100644 index 00000000000..c786afaed2d --- /dev/null +++ b/queue-5.4/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch @@ -0,0 +1,53 @@ +From 25ab8ebd2345274483e666c265c9baee751c6818 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2020 02:17:57 -0500 +Subject: ftrace: Add comment to why rcu_dereference_sched() is open coded + +From: Steven Rostedt (VMware) + +[ Upstream commit 16052dd5bdfa16dbe18d8c1d4cde2ddab9d23177 ] + +Because the function graph tracer can execute in sections where RCU is not +"watching", the rcu_dereference_sched() for the has needs to be open coded. +This is fine because the RCU "flavor" of the ftrace hash is protected by +its own RCU handling (it does its own little synchronization on every CPU +and does not rely on RCU sched). + +Acked-by: Joel Fernandes (Google) +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index c4fd5731d6b37..08647723cfab9 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -943,6 +943,11 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + + preempt_disable_notrace(); + ++ /* ++ * Have to open code "rcu_dereference_sched()" because the ++ * function graph tracer can be called when RCU is not ++ * "watching". ++ */ + hash = rcu_dereference_protected(ftrace_graph_hash, !preemptible()); + + if (ftrace_hash_empty(hash)) { +@@ -990,6 +995,11 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr) + + preempt_disable_notrace(); + ++ /* ++ * Have to open code "rcu_dereference_sched()" because the ++ * function graph tracer can be called when RCU is not ++ * "watching". ++ */ + notrace_hash = rcu_dereference_protected(ftrace_graph_notrace_hash, + !preemptible()); + +-- +2.20.1 + diff --git a/queue-5.4/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch b/queue-5.4/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch new file mode 100644 index 00000000000..e37091468e4 --- /dev/null +++ b/queue-5.4/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch @@ -0,0 +1,71 @@ +From 3062c7d6c0ae324f90d1dd7f551a439d434b0bc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2020 09:20:32 -0500 +Subject: ftrace: Protect ftrace_graph_hash with ftrace_sync + +From: Steven Rostedt (VMware) + +[ Upstream commit 54a16ff6f2e50775145b210bcd94d62c3c2af117 ] + +As function_graph tracer can run when RCU is not "watching", it can not be +protected by synchronize_rcu() it requires running a task on each CPU before +it can be freed. Calling schedule_on_each_cpu(ftrace_sync) needs to be used. + +Link: https://lore.kernel.org/r/20200205131110.GT2935@paulmck-ThinkPad-P72 + +Cc: stable@vger.kernel.org +Fixes: b9b0c831bed26 ("ftrace: Convert graph filter to use hash tables") +Reported-by: "Paul E. McKenney" +Reviewed-by: Joel Fernandes (Google) +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/ftrace.c | 11 +++++++++-- + kernel/trace/trace.h | 2 ++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index d297a8bdc681a..407d8bf4ed93e 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -5378,8 +5378,15 @@ ftrace_graph_release(struct inode *inode, struct file *file) + + mutex_unlock(&graph_lock); + +- /* Wait till all users are no longer using the old hash */ +- synchronize_rcu(); ++ /* ++ * We need to do a hard force of sched synchronization. ++ * This is because we use preempt_disable() to do RCU, but ++ * the function tracers can be called where RCU is not watching ++ * (like before user_exit()). We can not rely on the RCU ++ * infrastructure to do the synchronization, thus we must do it ++ * ourselves. ++ */ ++ schedule_on_each_cpu(ftrace_sync); + + free_ftrace_hash(old_hash); + } +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 08647723cfab9..a3c29d5fcc616 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -947,6 +947,7 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + * Have to open code "rcu_dereference_sched()" because the + * function graph tracer can be called when RCU is not + * "watching". ++ * Protected with schedule_on_each_cpu(ftrace_sync) + */ + hash = rcu_dereference_protected(ftrace_graph_hash, !preemptible()); + +@@ -999,6 +1000,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr) + * Have to open code "rcu_dereference_sched()" because the + * function graph tracer can be called when RCU is not + * "watching". ++ * Protected with schedule_on_each_cpu(ftrace_sync) + */ + notrace_hash = rcu_dereference_protected(ftrace_graph_notrace_hash, + !preemptible()); +-- +2.20.1 + diff --git a/queue-5.4/scsi-qla2xxx-fix-stuck-login-session-using-prli_pend.patch b/queue-5.4/scsi-qla2xxx-fix-stuck-login-session-using-prli_pend.patch new file mode 100644 index 00000000000..aa0d821de5d --- /dev/null +++ b/queue-5.4/scsi-qla2xxx-fix-stuck-login-session-using-prli_pend.patch @@ -0,0 +1,141 @@ +From 178de4af6c11a8171e2633b20bf83c4b6e1e9747 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2019 14:06:11 -0800 +Subject: scsi: qla2xxx: Fix stuck login session using prli_pend_timer + +From: Quinn Tran + +[ Upstream commit 8aaac2d7da873aebeba92c666f82c00bbd74aaf9 ] + +Session is stuck if driver sees FW has received a PRLI. Driver allows FW to +finish with processing of PRLI by checking back with FW at a later time to +see if the PRLI has finished. Instead, driver failed to push forward after +re-checking PRLI completion. + +Fixes: ce0ba496dccf ("scsi: qla2xxx: Fix stuck login session") +Cc: stable@vger.kernel.org # 5.3 +Link: https://lore.kernel.org/r/20191217220617.28084-9-hmadhani@marvell.com +Signed-off-by: Quinn Tran +Signed-off-by: Himanshu Madhani +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_def.h | 5 +++++ + drivers/scsi/qla2xxx/qla_init.c | 34 +++++++++++++++++++++++-------- + drivers/scsi/qla2xxx/qla_target.c | 1 + + 3 files changed, 32 insertions(+), 8 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index 1eb3fe281cc3c..c57b95a206888 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -2402,6 +2402,7 @@ typedef struct fc_port { + unsigned int scan_needed:1; + unsigned int n2n_flag:1; + unsigned int explicit_logout:1; ++ unsigned int prli_pend_timer:1; + + struct completion nvme_del_done; + uint32_t nvme_prli_service_param; +@@ -2428,6 +2429,7 @@ typedef struct fc_port { + struct work_struct free_work; + struct work_struct reg_work; + uint64_t jiffies_at_registration; ++ unsigned long prli_expired; + struct qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; + + uint16_t tgt_id; +@@ -4821,6 +4823,9 @@ struct sff_8247_a0 { + ha->current_topology == ISP_CFG_N || \ + !ha->current_topology) + ++#define PRLI_PHASE(_cls) \ ++ ((_cls == DSC_LS_PRLI_PEND) || (_cls == DSC_LS_PRLI_COMP)) ++ + #include "qla_target.h" + #include "qla_gbl.h" + #include "qla_dbg.h" +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 9ffaa920fc8f8..ac4c47fc5f4c1 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -686,7 +686,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, + port_id_t id; + u64 wwn; + u16 data[2]; +- u8 current_login_state; ++ u8 current_login_state, nvme_cls; + + fcport = ea->fcport; + ql_dbg(ql_dbg_disc, vha, 0xffff, +@@ -745,10 +745,17 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, + + loop_id = le16_to_cpu(e->nport_handle); + loop_id = (loop_id & 0x7fff); +- if (fcport->fc4f_nvme) +- current_login_state = e->current_login_state >> 4; +- else +- current_login_state = e->current_login_state & 0xf; ++ nvme_cls = e->current_login_state >> 4; ++ current_login_state = e->current_login_state & 0xf; ++ ++ if (PRLI_PHASE(nvme_cls)) { ++ current_login_state = nvme_cls; ++ fcport->fc4_type &= ~FS_FC4TYPE_FCP; ++ fcport->fc4_type |= FS_FC4TYPE_NVME; ++ } else if (PRLI_PHASE(current_login_state)) { ++ fcport->fc4_type |= FS_FC4TYPE_FCP; ++ fcport->fc4_type &= ~FS_FC4TYPE_NVME; ++ } + + + ql_dbg(ql_dbg_disc, vha, 0x20e2, +@@ -1219,12 +1226,19 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport) + struct srb_iocb *lio; + int rval = QLA_FUNCTION_FAILED; + +- if (!vha->flags.online) ++ if (!vha->flags.online) { ++ ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC exit\n", ++ __func__, __LINE__, fcport->port_name); + return rval; ++ } + +- if (fcport->fw_login_state == DSC_LS_PLOGI_PEND || +- fcport->fw_login_state == DSC_LS_PRLI_PEND) ++ if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND || ++ fcport->fw_login_state == DSC_LS_PRLI_PEND) && ++ qla_dual_mode_enabled(vha)) { ++ ql_dbg(ql_dbg_disc, vha, 0xffff, "%s %d %8phC exit\n", ++ __func__, __LINE__, fcport->port_name); + return rval; ++ } + + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) +@@ -1602,6 +1616,10 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport) + break; + default: + if (fcport->login_pause) { ++ ql_dbg(ql_dbg_disc, vha, 0x20d8, ++ "%s %d %8phC exit\n", ++ __func__, __LINE__, ++ fcport->port_name); + fcport->last_rscn_gen = fcport->rscn_gen; + fcport->last_login_gen = fcport->login_gen; + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); +diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c +index 74a378a91b71e..cb8a892e2d393 100644 +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1257,6 +1257,7 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess) + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; + spin_unlock_irqrestore(&sess->vha->work_lock, flags); + ++ sess->prli_pend_timer = 0; + sess->disc_state = DSC_DELETE_PEND; + + qla24xx_chk_fcp_state(sess); +-- +2.20.1 + diff --git a/queue-5.4/series b/queue-5.4/series index 53d8c3b7c7b..ca19e92c342 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -131,3 +131,10 @@ dm-crypt-fix-gfp-flags-passed-to-skcipher_request_alloc.patch dm-crypt-fix-benbi-iv-constructor-crash-if-used-in-authenticated-mode.patch dm-thin-metadata-use-pool-locking-at-end-of-dm_pool_metadata_close.patch dm-fix-potential-for-q-make_request_fn-null-pointer.patch +scsi-qla2xxx-fix-stuck-login-session-using-prli_pend.patch +asoc-sof-introduce-state-machine-for-fw-boot.patch +asoc-sof-core-release-resources-on-errors-in-probe_c.patch +tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch +tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch +ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch +ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch diff --git a/queue-5.4/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch b/queue-5.4/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch new file mode 100644 index 00000000000..4039d79254d --- /dev/null +++ b/queue-5.4/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch @@ -0,0 +1,77 @@ +From eb567e8f0e2f72e5ec87c486ce9f4dc8a26a3bbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Feb 2020 12:57:04 +0530 +Subject: tracing: Annotate ftrace_graph_hash pointer with __rcu + +From: Amol Grover + +[ Upstream commit 24a9729f831462b1d9d61dc85ecc91c59037243f ] + +Fix following instances of sparse error +kernel/trace/ftrace.c:5664:29: error: incompatible types in comparison +kernel/trace/ftrace.c:5785:21: error: incompatible types in comparison +kernel/trace/ftrace.c:5864:36: error: incompatible types in comparison +kernel/trace/ftrace.c:5866:25: error: incompatible types in comparison + +Use rcu_dereference_protected to access the __rcu annotated pointer. + +Link: http://lkml.kernel.org/r/20200201072703.17330-1-frextrite@gmail.com + +Reviewed-by: Joel Fernandes (Google) +Signed-off-by: Amol Grover +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/ftrace.c | 2 +- + kernel/trace/trace.h | 9 ++++++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index 0708a41cfe2de..b38c6af10da5b 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -5102,7 +5102,7 @@ static const struct file_operations ftrace_notrace_fops = { + + static DEFINE_MUTEX(graph_lock); + +-struct ftrace_hash *ftrace_graph_hash = EMPTY_HASH; ++struct ftrace_hash __rcu *ftrace_graph_hash = EMPTY_HASH; + struct ftrace_hash *ftrace_graph_notrace_hash = EMPTY_HASH; + + enum graph_filter_type { +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index d685c61085c0d..f8fb3786af72a 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -932,22 +932,25 @@ extern void __trace_graph_return(struct trace_array *tr, + unsigned long flags, int pc); + + #ifdef CONFIG_DYNAMIC_FTRACE +-extern struct ftrace_hash *ftrace_graph_hash; ++extern struct ftrace_hash __rcu *ftrace_graph_hash; + extern struct ftrace_hash *ftrace_graph_notrace_hash; + + static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + { + unsigned long addr = trace->func; + int ret = 0; ++ struct ftrace_hash *hash; + + preempt_disable_notrace(); + +- if (ftrace_hash_empty(ftrace_graph_hash)) { ++ hash = rcu_dereference_protected(ftrace_graph_hash, !preemptible()); ++ ++ if (ftrace_hash_empty(hash)) { + ret = 1; + goto out; + } + +- if (ftrace_lookup_ip(ftrace_graph_hash, addr)) { ++ if (ftrace_lookup_ip(hash, addr)) { + + /* + * This needs to be cleared on the return functions +-- +2.20.1 + diff --git a/queue-5.4/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch b/queue-5.4/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch new file mode 100644 index 00000000000..25a44851e92 --- /dev/null +++ b/queue-5.4/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch @@ -0,0 +1,72 @@ +From 3648a785ae0fef25dee2fc95227842f8ec82e03c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Feb 2020 11:27:02 +0530 +Subject: tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu + +From: Amol Grover + +[ Upstream commit fd0e6852c407dd9aefc594f54ddcc21d84803d3b ] + +Fix following instances of sparse error +kernel/trace/ftrace.c:5667:29: error: incompatible types in comparison +kernel/trace/ftrace.c:5813:21: error: incompatible types in comparison +kernel/trace/ftrace.c:5868:36: error: incompatible types in comparison +kernel/trace/ftrace.c:5870:25: error: incompatible types in comparison + +Use rcu_dereference_protected to dereference the newly annotated pointer. + +Link: http://lkml.kernel.org/r/20200205055701.30195-1-frextrite@gmail.com + +Signed-off-by: Amol Grover +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + kernel/trace/ftrace.c | 2 +- + kernel/trace/trace.h | 8 ++++++-- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c +index b38c6af10da5b..d297a8bdc681a 100644 +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -5103,7 +5103,7 @@ static const struct file_operations ftrace_notrace_fops = { + static DEFINE_MUTEX(graph_lock); + + struct ftrace_hash __rcu *ftrace_graph_hash = EMPTY_HASH; +-struct ftrace_hash *ftrace_graph_notrace_hash = EMPTY_HASH; ++struct ftrace_hash __rcu *ftrace_graph_notrace_hash = EMPTY_HASH; + + enum graph_filter_type { + GRAPH_FILTER_NOTRACE = 0, +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index f8fb3786af72a..c4fd5731d6b37 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -933,7 +933,7 @@ extern void __trace_graph_return(struct trace_array *tr, + + #ifdef CONFIG_DYNAMIC_FTRACE + extern struct ftrace_hash __rcu *ftrace_graph_hash; +-extern struct ftrace_hash *ftrace_graph_notrace_hash; ++extern struct ftrace_hash __rcu *ftrace_graph_notrace_hash; + + static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace) + { +@@ -986,10 +986,14 @@ static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace) + static inline int ftrace_graph_notrace_addr(unsigned long addr) + { + int ret = 0; ++ struct ftrace_hash *notrace_hash; + + preempt_disable_notrace(); + +- if (ftrace_lookup_ip(ftrace_graph_notrace_hash, addr)) ++ notrace_hash = rcu_dereference_protected(ftrace_graph_notrace_hash, ++ !preemptible()); ++ ++ if (ftrace_lookup_ip(notrace_hash, addr)) + ret = 1; + + preempt_enable_notrace(); +-- +2.20.1 +