]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Fri, 7 Feb 2020 16:10:36 +0000 (11:10 -0500)
committerSasha Levin <sashal@kernel.org>
Fri, 7 Feb 2020 16:10:36 +0000 (11:10 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/asoc-sof-core-release-resources-on-errors-in-probe_c.patch [new file with mode: 0644]
queue-5.4/asoc-sof-introduce-state-machine-for-fw-boot.patch [new file with mode: 0644]
queue-5.4/ftrace-add-comment-to-why-rcu_dereference_sched-is-o.patch [new file with mode: 0644]
queue-5.4/ftrace-protect-ftrace_graph_hash-with-ftrace_sync.patch [new file with mode: 0644]
queue-5.4/scsi-qla2xxx-fix-stuck-login-session-using-prli_pend.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/tracing-annotate-ftrace_graph_hash-pointer-with-__rc.patch [new file with mode: 0644]
queue-5.4/tracing-annotate-ftrace_graph_notrace_hash-pointer-w.patch [new file with mode: 0644]

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 (file)
index 0000000..8e2e29e
--- /dev/null
@@ -0,0 +1,120 @@
+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
+
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 (file)
index 0000000..9f42c62
--- /dev/null
@@ -0,0 +1,328 @@
+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
+
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 (file)
index 0000000..c786afa
--- /dev/null
@@ -0,0 +1,53 @@
+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
+
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 (file)
index 0000000..e370914
--- /dev/null
@@ -0,0 +1,71 @@
+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
+
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 (file)
index 0000000..aa0d821
--- /dev/null
@@ -0,0 +1,141 @@
+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
+
index 53d8c3b7c7be884a6dc4a45a7b753822b52749be..ca19e92c342ec28e22aab96e816dc7dac668bb54 100644 (file)
@@ -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 (file)
index 0000000..4039d79
--- /dev/null
@@ -0,0 +1,77 @@
+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
+
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 (file)
index 0000000..25a4485
--- /dev/null
@@ -0,0 +1,72 @@
+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
+