--- /dev/null
+From 89f645b6ec6a76dc6108f41720b047ef698ca4ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Jan 2020 15:36:21 -0600
+Subject: ASoC: SOF: core: release resources on errors in probe_continue
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ 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 <tiwai@suse.de>
+Co-developed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Bugzilla: http://bugzilla.suse.com/show_bug.cgi?id=1161246
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Link: https://lore.kernel.org/r/20200124213625.30186-4-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 1b12b51278e493b275c5038b0d0d1fbbaf3d6646 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Dec 2019 18:26:09 -0600
+Subject: ASoC: SOF: Introduce state machine for FW boot
+
+From: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+
+[ 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 <cujomalainey@chromium.org>
+Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
+Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20191218002616.7652-2-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 25ab8ebd2345274483e666c265c9baee751c6818 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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) <rostedt@goodmis.org>
+
+[ 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) <joel@joelfernandes.org>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 3062c7d6c0ae324f90d1dd7f551a439d434b0bc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2020 09:20:32 -0500
+Subject: ftrace: Protect ftrace_graph_hash with ftrace_sync
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+[ 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" <paulmck@kernel.org>
+Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 178de4af6c11a8171e2633b20bf83c4b6e1e9747 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Dec 2019 14:06:11 -0800
+Subject: scsi: qla2xxx: Fix stuck login session using prli_pend_timer
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ 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 <qutran@marvell.com>
+Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
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
--- /dev/null
+From eb567e8f0e2f72e5ec87c486ce9f4dc8a26a3bbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Feb 2020 12:57:04 +0530
+Subject: tracing: Annotate ftrace_graph_hash pointer with __rcu
+
+From: Amol Grover <frextrite@gmail.com>
+
+[ 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) <joel@joelfernandes.org>
+Signed-off-by: Amol Grover <frextrite@gmail.com>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
--- /dev/null
+From 3648a785ae0fef25dee2fc95227842f8ec82e03c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Feb 2020 11:27:02 +0530
+Subject: tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
+
+From: Amol Grover <frextrite@gmail.com>
+
+[ 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 <frextrite@gmail.com>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+