]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Thu, 4 Jun 2020 19:29:40 +0000 (15:29 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 4 Jun 2020 19:29:40 +0000 (15:29 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/asoc-intel-fix-the-card-names.patch [new file with mode: 0644]
queue-5.4/drm-i915-fix-port-checks-for-mst-support-on-gen-11.patch [new file with mode: 0644]
queue-5.4/powerpc-powernv-avoid-re-registration-of-imc-debugfs.patch [new file with mode: 0644]
queue-5.4/powerpc-xmon-restrict-when-kernel-is-locked-down.patch [new file with mode: 0644]
queue-5.4/rdma-qedr-fix-qpids-xarray-api-used.patch [new file with mode: 0644]
queue-5.4/rdma-qedr-fix-synchronization-methods-and-memory-lea.patch [new file with mode: 0644]
queue-5.4/s390-ftrace-save-traced-function-caller.patch [new file with mode: 0644]
queue-5.4/scsi-hisi_sas-check-sas_port-before-using-it.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/spi-dw-use-smp_mb-to-avoid-sending-spi-data-error.patch [new file with mode: 0644]

diff --git a/queue-5.4/asoc-intel-fix-the-card-names.patch b/queue-5.4/asoc-intel-fix-the-card-names.patch
new file mode 100644 (file)
index 0000000..8b14bab
--- /dev/null
@@ -0,0 +1,69 @@
+From 1ed972e95341fdde7361d9cf4cf35d73dda25d82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Oct 2019 17:46:24 +0100
+Subject: ASoC: intel - fix the card names
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+[ Upstream commit d745cc1ab65945b2d17ec9c5652f38299c054649 ]
+
+Those strings are exposed to the user space as the
+card name thus used in the GUIs. The common
+standard is to avoid '_' here. The worst case
+is 'sof-skl_hda_card' string.
+
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Cc: Mark Brown <broonie@kernel.org>
+Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20191028164624.14334-1-perex@perex.cz
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 2 +-
+ sound/soc/intel/boards/skl_hda_dsp_generic.c        | 2 +-
+ sound/soc/intel/boards/sof_rt5682.c                 | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
+index 67b276a65a8d..8ad31c91fc75 100644
+--- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
++++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
+@@ -626,7 +626,7 @@ static int kabylake_card_late_probe(struct snd_soc_card *card)
+  * kabylake audio machine driver for  MAX98927 + RT5514 + RT5663
+  */
+ static struct snd_soc_card kabylake_audio_card = {
+-      .name = "kbl_r5514_5663_max",
++      .name = "kbl-r5514-5663-max",
+       .owner = THIS_MODULE,
+       .dai_link = kabylake_dais,
+       .num_links = ARRAY_SIZE(kabylake_dais),
+diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
+index 1778acdc367c..e8d676c192f6 100644
+--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
++++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
+@@ -90,7 +90,7 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
+ }
+ static struct snd_soc_card hda_soc_card = {
+-      .name = "skl_hda_card",
++      .name = "hda-dsp",
+       .owner = THIS_MODULE,
+       .dai_link = skl_hda_be_dai_links,
+       .dapm_widgets = skl_hda_widgets,
+diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
+index 06b7d6c6c9a0..302ca1920791 100644
+--- a/sound/soc/intel/boards/sof_rt5682.c
++++ b/sound/soc/intel/boards/sof_rt5682.c
+@@ -374,7 +374,7 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd)
+ /* sof audio machine driver for rt5682 codec */
+ static struct snd_soc_card sof_audio_card_rt5682 = {
+-      .name = "sof_rt5682",
++      .name = "rt5682", /* the sof- prefix is added by the core */
+       .owner = THIS_MODULE,
+       .controls = sof_controls,
+       .num_controls = ARRAY_SIZE(sof_controls),
+-- 
+2.25.1
+
diff --git a/queue-5.4/drm-i915-fix-port-checks-for-mst-support-on-gen-11.patch b/queue-5.4/drm-i915-fix-port-checks-for-mst-support-on-gen-11.patch
new file mode 100644 (file)
index 0000000..56cbb6c
--- /dev/null
@@ -0,0 +1,93 @@
+From e606dcb3035d83e8908a60ace782708528a8de54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Oct 2019 18:09:03 -0700
+Subject: drm/i915: fix port checks for MST support on gen >= 11
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+
+[ Upstream commit 10d987fd1b7baceaafa78d805e71427ab735b4e4 ]
+
+Both Ice Lake and Elkhart Lake (gen 11) support MST on all external
+connections except DDI A. Tiger Lake (gen 12) supports on all external
+connections.
+
+Move the check to happen inside intel_dp_mst_encoder_init() and add
+specific platform checks.
+
+v2: Replace != with == checks for ports on gen < 11 (Ville)
+
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191015164029.18431-3-lucas.demarchi@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp.c     |  7 ++-----
+ drivers/gpu/drm/i915/display/intel_dp_mst.c | 22 +++++++++++++++------
+ 2 files changed, 18 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
+index 9b15ac4f2fb6..4ab6531a4a74 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -7218,11 +7218,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+               intel_connector->get_hw_state = intel_connector_get_hw_state;
+       /* init MST on ports that can support it */
+-      if (HAS_DP_MST(dev_priv) && !intel_dp_is_edp(intel_dp) &&
+-          (port == PORT_B || port == PORT_C ||
+-           port == PORT_D || port == PORT_F))
+-              intel_dp_mst_encoder_init(intel_dig_port,
+-                                        intel_connector->base.base.id);
++      intel_dp_mst_encoder_init(intel_dig_port,
++                                intel_connector->base.base.id);
+       if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+               intel_dp_aux_fini(intel_dp);
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+index 600873c796d0..74d45a0eecb8 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -653,21 +653,31 @@ intel_dp_mst_encoder_active_links(struct intel_digital_port *intel_dig_port)
+ int
+ intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_base_id)
+ {
++      struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev);
+       struct intel_dp *intel_dp = &intel_dig_port->dp;
+-      struct drm_device *dev = intel_dig_port->base.base.dev;
++      enum port port = intel_dig_port->base.port;
+       int ret;
+-      intel_dp->can_mst = true;
++      if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp))
++              return 0;
++
++      if (INTEL_GEN(i915) < 12 && port == PORT_A)
++              return 0;
++
++      if (INTEL_GEN(i915) < 11 && port == PORT_E)
++              return 0;
++
+       intel_dp->mst_mgr.cbs = &mst_cbs;
+       /* create encoders */
+       intel_dp_create_fake_mst_encoders(intel_dig_port);
+-      ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, dev,
++      ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm,
+                                          &intel_dp->aux, 16, 3, conn_base_id);
+-      if (ret) {
+-              intel_dp->can_mst = false;
++      if (ret)
+               return ret;
+-      }
++
++      intel_dp->can_mst = true;
++
+       return 0;
+ }
+-- 
+2.25.1
+
diff --git a/queue-5.4/powerpc-powernv-avoid-re-registration-of-imc-debugfs.patch b/queue-5.4/powerpc-powernv-avoid-re-registration-of-imc-debugfs.patch
new file mode 100644 (file)
index 0000000..087c50a
--- /dev/null
@@ -0,0 +1,163 @@
+From 368677f69fa736f0920d9815693af235c74abaf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2019 12:50:35 +0530
+Subject: powerpc/powernv: Avoid re-registration of imc debugfs directory
+
+From: Anju T Sudhakar <anju@linux.vnet.ibm.com>
+
+[ Upstream commit 48e626ac85b43cc589dd1b3b8004f7f85f03544d ]
+
+export_imc_mode_and_cmd() function which creates the debugfs interface
+for imc-mode and imc-command, is invoked when each nest pmu units is
+registered.
+
+When the first nest pmu unit is registered, export_imc_mode_and_cmd()
+creates 'imc' directory under `/debug/powerpc/`. In the subsequent
+invocations debugfs_create_dir() function returns, since the directory
+already exists.
+
+The recent commit <c33d442328f55> (debugfs: make error message a bit
+more verbose), throws a warning if we try to invoke
+`debugfs_create_dir()` with an already existing directory name.
+
+Address this warning by making the debugfs directory registration in
+the opal_imc_counters_probe() function, i.e invoke
+export_imc_mode_and_cmd() function from the probe function.
+
+Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com>
+Tested-by: Nageswara R Sastry <nasastry@in.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20191127072035.4283-1-anju@linux.vnet.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/powernv/opal-imc.c | 39 ++++++++++-------------
+ 1 file changed, 16 insertions(+), 23 deletions(-)
+
+diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c
+index 7ccc5c85c74e..000b350d4060 100644
+--- a/arch/powerpc/platforms/powernv/opal-imc.c
++++ b/arch/powerpc/platforms/powernv/opal-imc.c
+@@ -59,10 +59,6 @@ static void export_imc_mode_and_cmd(struct device_node *node,
+       imc_debugfs_parent = debugfs_create_dir("imc", powerpc_debugfs_root);
+-      /*
+-       * Return here, either because 'imc' directory already exists,
+-       * Or failed to create a new one.
+-       */
+       if (!imc_debugfs_parent)
+               return;
+@@ -135,7 +131,6 @@ static int imc_get_mem_addr_nest(struct device_node *node,
+       }
+       pmu_ptr->imc_counter_mmaped = true;
+-      export_imc_mode_and_cmd(node, pmu_ptr);
+       kfree(base_addr_arr);
+       kfree(chipid_arr);
+       return 0;
+@@ -151,7 +146,7 @@ static int imc_get_mem_addr_nest(struct device_node *node,
+  *                and domain as the inputs.
+  * Allocates memory for the struct imc_pmu, sets up its domain, size and offsets
+  */
+-static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
++static struct imc_pmu *imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
+ {
+       int ret = 0;
+       struct imc_pmu *pmu_ptr;
+@@ -159,27 +154,23 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
+       /* Return for unknown domain */
+       if (domain < 0)
+-              return -EINVAL;
++              return NULL;
+       /* memory for pmu */
+       pmu_ptr = kzalloc(sizeof(*pmu_ptr), GFP_KERNEL);
+       if (!pmu_ptr)
+-              return -ENOMEM;
++              return NULL;
+       /* Set the domain */
+       pmu_ptr->domain = domain;
+       ret = of_property_read_u32(parent, "size", &pmu_ptr->counter_mem_size);
+-      if (ret) {
+-              ret = -EINVAL;
++      if (ret)
+               goto free_pmu;
+-      }
+       if (!of_property_read_u32(parent, "offset", &offset)) {
+-              if (imc_get_mem_addr_nest(parent, pmu_ptr, offset)) {
+-                      ret = -EINVAL;
++              if (imc_get_mem_addr_nest(parent, pmu_ptr, offset))
+                       goto free_pmu;
+-              }
+       }
+       /* Function to register IMC pmu */
+@@ -190,14 +181,14 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
+               if (pmu_ptr->domain == IMC_DOMAIN_NEST)
+                       kfree(pmu_ptr->mem_info);
+               kfree(pmu_ptr);
+-              return ret;
++              return NULL;
+       }
+-      return 0;
++      return pmu_ptr;
+ free_pmu:
+       kfree(pmu_ptr);
+-      return ret;
++      return NULL;
+ }
+ static void disable_nest_pmu_counters(void)
+@@ -254,6 +245,7 @@ int get_max_nest_dev(void)
+ static int opal_imc_counters_probe(struct platform_device *pdev)
+ {
+       struct device_node *imc_dev = pdev->dev.of_node;
++      struct imc_pmu *pmu;
+       int pmu_count = 0, domain;
+       bool core_imc_reg = false, thread_imc_reg = false;
+       u32 type;
+@@ -269,6 +261,7 @@ static int opal_imc_counters_probe(struct platform_device *pdev)
+       }
+       for_each_compatible_node(imc_dev, NULL, IMC_DTB_UNIT_COMPAT) {
++              pmu = NULL;
+               if (of_property_read_u32(imc_dev, "type", &type)) {
+                       pr_warn("IMC Device without type property\n");
+                       continue;
+@@ -300,9 +293,13 @@ static int opal_imc_counters_probe(struct platform_device *pdev)
+                       break;
+               }
+-              if (!imc_pmu_create(imc_dev, pmu_count, domain)) {
+-                      if (domain == IMC_DOMAIN_NEST)
++              pmu = imc_pmu_create(imc_dev, pmu_count, domain);
++              if (pmu != NULL) {
++                      if (domain == IMC_DOMAIN_NEST) {
++                              if (!imc_debugfs_parent)
++                                      export_imc_mode_and_cmd(imc_dev, pmu);
+                               pmu_count++;
++                      }
+                       if (domain == IMC_DOMAIN_CORE)
+                               core_imc_reg = true;
+                       if (domain == IMC_DOMAIN_THREAD)
+@@ -310,10 +307,6 @@ static int opal_imc_counters_probe(struct platform_device *pdev)
+               }
+       }
+-      /* If none of the nest units are registered, remove debugfs interface */
+-      if (pmu_count == 0)
+-              debugfs_remove_recursive(imc_debugfs_parent);
+-
+       /* If core imc is not registered, unregister thread-imc */
+       if (!core_imc_reg && thread_imc_reg)
+               unregister_thread_imc();
+-- 
+2.25.1
+
diff --git a/queue-5.4/powerpc-xmon-restrict-when-kernel-is-locked-down.patch b/queue-5.4/powerpc-xmon-restrict-when-kernel-is-locked-down.patch
new file mode 100644 (file)
index 0000000..0a0a972
--- /dev/null
@@ -0,0 +1,314 @@
+From 6addd378390a244f2abd0066ddd19557b5606caf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Sep 2019 01:11:24 -0500
+Subject: powerpc/xmon: Restrict when kernel is locked down
+
+From: Christopher M. Riedl <cmr@informatik.wtf>
+
+[ Upstream commit 69393cb03ccdf29f3b452d3482ef918469d1c098 ]
+
+Xmon should be either fully or partially disabled depending on the
+kernel lockdown state.
+
+Put xmon into read-only mode for lockdown=integrity and prevent user
+entry into xmon when lockdown=confidentiality. Xmon checks the lockdown
+state on every attempted entry:
+
+ (1) during early xmon'ing
+
+ (2) when triggered via sysrq
+
+ (3) when toggled via debugfs
+
+ (4) when triggered via a previously enabled breakpoint
+
+The following lockdown state transitions are handled:
+
+ (1) lockdown=none -> lockdown=integrity
+     set xmon read-only mode
+
+ (2) lockdown=none -> lockdown=confidentiality
+     clear all breakpoints, set xmon read-only mode,
+     prevent user re-entry into xmon
+
+ (3) lockdown=integrity -> lockdown=confidentiality
+     clear all breakpoints, set xmon read-only mode,
+     prevent user re-entry into xmon
+
+Suggested-by: Andrew Donnellan <ajd@linux.ibm.com>
+Signed-off-by: Christopher M. Riedl <cmr@informatik.wtf>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20190907061124.1947-3-cmr@informatik.wtf
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/xmon/xmon.c     | 103 ++++++++++++++++++++++++++++-------
+ include/linux/security.h     |   2 +
+ security/lockdown/lockdown.c |   2 +
+ 3 files changed, 86 insertions(+), 21 deletions(-)
+
+diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
+index 8057aafd5f5e..6d130c89fbd8 100644
+--- a/arch/powerpc/xmon/xmon.c
++++ b/arch/powerpc/xmon/xmon.c
+@@ -25,6 +25,7 @@
+ #include <linux/nmi.h>
+ #include <linux/ctype.h>
+ #include <linux/highmem.h>
++#include <linux/security.h>
+ #include <asm/debugfs.h>
+ #include <asm/ptrace.h>
+@@ -187,6 +188,8 @@ static void dump_tlb_44x(void);
+ static void dump_tlb_book3e(void);
+ #endif
++static void clear_all_bpt(void);
++
+ #ifdef CONFIG_PPC64
+ #define REG           "%.16lx"
+ #else
+@@ -283,10 +286,38 @@ Commands:\n\
+ "  U  show uptime information\n"
+ "  ?  help\n"
+ "  # n        limit output to n lines per page (for dp, dpa, dl)\n"
+-"  zr reboot\n\
+-  zh  halt\n"
++"  zr reboot\n"
++"  zh halt\n"
+ ;
++#ifdef CONFIG_SECURITY
++static bool xmon_is_locked_down(void)
++{
++      static bool lockdown;
++
++      if (!lockdown) {
++              lockdown = !!security_locked_down(LOCKDOWN_XMON_RW);
++              if (lockdown) {
++                      printf("xmon: Disabled due to kernel lockdown\n");
++                      xmon_is_ro = true;
++              }
++      }
++
++      if (!xmon_is_ro) {
++              xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR);
++              if (xmon_is_ro)
++                      printf("xmon: Read-only due to kernel lockdown\n");
++      }
++
++      return lockdown;
++}
++#else /* CONFIG_SECURITY */
++static inline bool xmon_is_locked_down(void)
++{
++      return false;
++}
++#endif
++
+ static struct pt_regs *xmon_regs;
+ static inline void sync(void)
+@@ -438,7 +469,10 @@ static bool wait_for_other_cpus(int ncpus)
+       return false;
+ }
+-#endif /* CONFIG_SMP */
++#else /* CONFIG_SMP */
++static inline void get_output_lock(void) {}
++static inline void release_output_lock(void) {}
++#endif
+ static inline int unrecoverable_excp(struct pt_regs *regs)
+ {
+@@ -455,6 +489,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+       int cmd = 0;
+       struct bpt *bp;
+       long recurse_jmp[JMP_BUF_LEN];
++      bool locked_down;
+       unsigned long offset;
+       unsigned long flags;
+ #ifdef CONFIG_SMP
+@@ -465,6 +500,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+       local_irq_save(flags);
+       hard_irq_disable();
++      locked_down = xmon_is_locked_down();
++
+       if (!fromipi) {
+               tracing_enabled = tracing_is_on();
+               tracing_off();
+@@ -518,7 +555,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+       if (!fromipi) {
+               get_output_lock();
+-              excprint(regs);
++              if (!locked_down)
++                      excprint(regs);
+               if (bp) {
+                       printf("cpu 0x%x stopped at breakpoint 0x%tx (",
+                              cpu, BP_NUM(bp));
+@@ -570,10 +608,14 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+               }
+               remove_bpts();
+               disable_surveillance();
+-              /* for breakpoint or single step, print the current instr. */
+-              if (bp || TRAP(regs) == 0xd00)
+-                      ppc_inst_dump(regs->nip, 1, 0);
+-              printf("enter ? for help\n");
++
++              if (!locked_down) {
++                      /* for breakpoint or single step, print curr insn */
++                      if (bp || TRAP(regs) == 0xd00)
++                              ppc_inst_dump(regs->nip, 1, 0);
++                      printf("enter ? for help\n");
++              }
++
+               mb();
+               xmon_gate = 1;
+               barrier();
+@@ -597,8 +639,9 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+                       spin_cpu_relax();
+                       touch_nmi_watchdog();
+               } else {
+-                      cmd = cmds(regs);
+-                      if (cmd != 0) {
++                      if (!locked_down)
++                              cmd = cmds(regs);
++                      if (locked_down || cmd != 0) {
+                               /* exiting xmon */
+                               insert_bpts();
+                               xmon_gate = 0;
+@@ -635,13 +678,16 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+                              "can't continue\n");
+               remove_bpts();
+               disable_surveillance();
+-              /* for breakpoint or single step, print the current instr. */
+-              if (bp || TRAP(regs) == 0xd00)
+-                      ppc_inst_dump(regs->nip, 1, 0);
+-              printf("enter ? for help\n");
++              if (!locked_down) {
++                      /* for breakpoint or single step, print current insn */
++                      if (bp || TRAP(regs) == 0xd00)
++                              ppc_inst_dump(regs->nip, 1, 0);
++                      printf("enter ? for help\n");
++              }
+       }
+-      cmd = cmds(regs);
++      if (!locked_down)
++              cmd = cmds(regs);
+       insert_bpts();
+       in_xmon = 0;
+@@ -670,7 +716,10 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
+               }
+       }
+ #endif
+-      insert_cpu_bpts();
++      if (locked_down)
++              clear_all_bpt();
++      else
++              insert_cpu_bpts();
+       touch_nmi_watchdog();
+       local_irq_restore(flags);
+@@ -3761,6 +3810,11 @@ static void xmon_init(int enable)
+ #ifdef CONFIG_MAGIC_SYSRQ
+ static void sysrq_handle_xmon(int key)
+ {
++      if (xmon_is_locked_down()) {
++              clear_all_bpt();
++              xmon_init(0);
++              return;
++      }
+       /* ensure xmon is enabled */
+       xmon_init(1);
+       debugger(get_irq_regs());
+@@ -3782,7 +3836,6 @@ static int __init setup_xmon_sysrq(void)
+ device_initcall(setup_xmon_sysrq);
+ #endif /* CONFIG_MAGIC_SYSRQ */
+-#ifdef CONFIG_DEBUG_FS
+ static void clear_all_bpt(void)
+ {
+       int i;
+@@ -3800,18 +3853,22 @@ static void clear_all_bpt(void)
+               iabr = NULL;
+               dabr.enabled = 0;
+       }
+-
+-      printf("xmon: All breakpoints cleared\n");
+ }
++#ifdef CONFIG_DEBUG_FS
+ static int xmon_dbgfs_set(void *data, u64 val)
+ {
+       xmon_on = !!val;
+       xmon_init(xmon_on);
+       /* make sure all breakpoints removed when disabling */
+-      if (!xmon_on)
++      if (!xmon_on) {
+               clear_all_bpt();
++              get_output_lock();
++              printf("xmon: All breakpoints cleared\n");
++              release_output_lock();
++      }
++
+       return 0;
+ }
+@@ -3837,7 +3894,11 @@ static int xmon_early __initdata;
+ static int __init early_parse_xmon(char *p)
+ {
+-      if (!p || strncmp(p, "early", 5) == 0) {
++      if (xmon_is_locked_down()) {
++              xmon_init(0);
++              xmon_early = 0;
++              xmon_on = 0;
++      } else if (!p || strncmp(p, "early", 5) == 0) {
+               /* just "xmon" is equivalent to "xmon=early" */
+               xmon_init(1);
+               xmon_early = 1;
+diff --git a/include/linux/security.h b/include/linux/security.h
+index 9df7547afc0c..fd022768e91d 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -117,12 +117,14 @@ enum lockdown_reason {
+       LOCKDOWN_MODULE_PARAMETERS,
+       LOCKDOWN_MMIOTRACE,
+       LOCKDOWN_DEBUGFS,
++      LOCKDOWN_XMON_WR,
+       LOCKDOWN_INTEGRITY_MAX,
+       LOCKDOWN_KCORE,
+       LOCKDOWN_KPROBES,
+       LOCKDOWN_BPF_READ,
+       LOCKDOWN_PERF,
+       LOCKDOWN_TRACEFS,
++      LOCKDOWN_XMON_RW,
+       LOCKDOWN_CONFIDENTIALITY_MAX,
+ };
+diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
+index 40b790536def..b2f87015d6e9 100644
+--- a/security/lockdown/lockdown.c
++++ b/security/lockdown/lockdown.c
+@@ -32,12 +32,14 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
+       [LOCKDOWN_MODULE_PARAMETERS] = "unsafe module parameters",
+       [LOCKDOWN_MMIOTRACE] = "unsafe mmio",
+       [LOCKDOWN_DEBUGFS] = "debugfs access",
++      [LOCKDOWN_XMON_WR] = "xmon write access",
+       [LOCKDOWN_INTEGRITY_MAX] = "integrity",
+       [LOCKDOWN_KCORE] = "/proc/kcore access",
+       [LOCKDOWN_KPROBES] = "use of kprobes",
+       [LOCKDOWN_BPF_READ] = "use of bpf to read kernel RAM",
+       [LOCKDOWN_PERF] = "unsafe use of perf",
+       [LOCKDOWN_TRACEFS] = "use of tracefs",
++      [LOCKDOWN_XMON_RW] = "xmon read and write access",
+       [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
+ };
+-- 
+2.25.1
+
diff --git a/queue-5.4/rdma-qedr-fix-qpids-xarray-api-used.patch b/queue-5.4/rdma-qedr-fix-qpids-xarray-api-used.patch
new file mode 100644 (file)
index 0000000..cba82e5
--- /dev/null
@@ -0,0 +1,76 @@
+From 6e2921b344c669d64aa9d197bc05c5b0a8d8eb2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Oct 2019 22:04:49 +0200
+Subject: RDMA/qedr: Fix qpids xarray api used
+
+From: Michal Kalderon <michal.kalderon@marvell.com>
+
+[ Upstream commit 5fdff18b4dc64e2d1e912ad2b90495cd487f791b ]
+
+The qpids xarray isn't accessed from irq context and therefore there
+is no need to use the xa_XXX_irq version of the apis.
+Remove the _irq.
+
+Fixes: b6014f9e5f39 ("qedr: Convert qpidr to XArray")
+Link: https://lore.kernel.org/r/20191027200451.28187-3-michal.kalderon@marvell.com
+Signed-off-by: Ariel Elior <ariel.elior@marvell.com>
+Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com>
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/qedr/main.c       | 2 +-
+ drivers/infiniband/hw/qedr/qedr_iw_cm.c | 2 +-
+ drivers/infiniband/hw/qedr/verbs.c      | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
+index b462eaca1ee3..4494dab8c3d8 100644
+--- a/drivers/infiniband/hw/qedr/main.c
++++ b/drivers/infiniband/hw/qedr/main.c
+@@ -360,7 +360,7 @@ static int qedr_alloc_resources(struct qedr_dev *dev)
+       xa_init_flags(&dev->srqs, XA_FLAGS_LOCK_IRQ);
+       if (IS_IWARP(dev)) {
+-              xa_init_flags(&dev->qps, XA_FLAGS_LOCK_IRQ);
++              xa_init(&dev->qps);
+               dev->iwarp_wq = create_singlethread_workqueue("qedr_iwarpq");
+       }
+diff --git a/drivers/infiniband/hw/qedr/qedr_iw_cm.c b/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+index 22881d4442b9..7fea74739c1f 100644
+--- a/drivers/infiniband/hw/qedr/qedr_iw_cm.c
++++ b/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+@@ -739,7 +739,7 @@ void qedr_iw_qp_rem_ref(struct ib_qp *ibqp)
+       struct qedr_qp *qp = get_qedr_qp(ibqp);
+       if (atomic_dec_and_test(&qp->refcnt)) {
+-              xa_erase_irq(&qp->dev->qps, qp->qp_id);
++              xa_erase(&qp->dev->qps, qp->qp_id);
+               kfree(qp);
+       }
+ }
+diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
+index a7ccca3c4f89..062165935441 100644
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -1926,7 +1926,7 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
+       qp->ibqp.qp_num = qp->qp_id;
+       if (rdma_protocol_iwarp(&dev->ibdev, 1)) {
+-              rc = xa_insert_irq(&dev->qps, qp->qp_id, qp, GFP_KERNEL);
++              rc = xa_insert(&dev->qps, qp->qp_id, qp, GFP_KERNEL);
+               if (rc)
+                       goto err;
+       }
+@@ -2500,7 +2500,7 @@ int qedr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+       if (atomic_dec_and_test(&qp->refcnt) &&
+           rdma_protocol_iwarp(&dev->ibdev, 1)) {
+-              xa_erase_irq(&dev->qps, qp->qp_id);
++              xa_erase(&dev->qps, qp->qp_id);
+               kfree(qp);
+       }
+       return 0;
+-- 
+2.25.1
+
diff --git a/queue-5.4/rdma-qedr-fix-synchronization-methods-and-memory-lea.patch b/queue-5.4/rdma-qedr-fix-synchronization-methods-and-memory-lea.patch
new file mode 100644 (file)
index 0000000..f9f9d4f
--- /dev/null
@@ -0,0 +1,552 @@
+From 3264196364537525ea9a0c42742443bb87bcccad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Oct 2019 22:04:50 +0200
+Subject: RDMA/qedr: Fix synchronization methods and memory leaks in qedr
+
+From: Michal Kalderon <michal.kalderon@marvell.com>
+
+[ Upstream commit 82af6d19d8d9227c22a53ff00b40fb2a4f9fce69 ]
+
+Re-design of the iWARP CM related objects reference counting and
+synchronization methods, to ensure operations are synchronized correctly
+and that memory allocated for "ep" is properly released. Also makes sure
+QP memory is not released before ep is finished accessing it.
+
+Where as the QP object is created/destroyed by external operations, the ep
+is created/destroyed by internal operations and represents the tcp
+connection associated with the QP.
+
+QP destruction flow:
+- needs to wait for ep establishment to complete (either successfully or
+  with error)
+- needs to wait for ep disconnect to be fully posted to avoid a race
+  condition of disconnect being called after reset.
+- both the operations above don't always happen, so we use atomic flags to
+  indicate whether the qp destruction flow needs to wait for these
+  completions or not, if the destroy is called before these operations
+  began, the flows will check the flags and not execute them ( connect /
+  disconnect).
+
+We use completion structure for waiting for the completions mentioned
+above.
+
+The QP refcnt was modified to kref object.  The EP has a kref added to it
+to handle additional worker thread accessing it.
+
+Memory Leaks - https://www.spinics.net/lists/linux-rdma/msg83762.html
+
+Concurrency not managed correctly -
+https://www.spinics.net/lists/linux-rdma/msg67949.html
+
+Fixes: de0089e692a9 ("RDMA/qedr: Add iWARP connection management qp related callbacks")
+Link: https://lore.kernel.org/r/20191027200451.28187-4-michal.kalderon@marvell.com
+Reported-by: Chuck Lever <chuck.lever@oracle.com>
+Reported-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Ariel Elior <ariel.elior@marvell.com>
+Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com>
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/qedr/qedr.h       |  23 +++-
+ drivers/infiniband/hw/qedr/qedr_iw_cm.c | 148 ++++++++++++++++--------
+ drivers/infiniband/hw/qedr/verbs.c      |  62 ++++++----
+ 3 files changed, 158 insertions(+), 75 deletions(-)
+
+diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h
+index 0cfd849b13d6..8e927f6c1520 100644
+--- a/drivers/infiniband/hw/qedr/qedr.h
++++ b/drivers/infiniband/hw/qedr/qedr.h
+@@ -40,6 +40,7 @@
+ #include <linux/qed/qed_rdma_if.h>
+ #include <linux/qed/qede_rdma.h>
+ #include <linux/qed/roce_common.h>
++#include <linux/completion.h>
+ #include "qedr_hsi_rdma.h"
+ #define QEDR_NODE_DESC "QLogic 579xx RoCE HCA"
+@@ -377,10 +378,20 @@ enum qedr_qp_err_bitmap {
+       QEDR_QP_ERR_RQ_PBL_FULL = 32,
+ };
++enum qedr_qp_create_type {
++      QEDR_QP_CREATE_NONE,
++      QEDR_QP_CREATE_USER,
++      QEDR_QP_CREATE_KERNEL,
++};
++
++enum qedr_iwarp_cm_flags {
++      QEDR_IWARP_CM_WAIT_FOR_CONNECT    = BIT(0),
++      QEDR_IWARP_CM_WAIT_FOR_DISCONNECT = BIT(1),
++};
++
+ struct qedr_qp {
+       struct ib_qp ibqp;      /* must be first */
+       struct qedr_dev *dev;
+-      struct qedr_iw_ep *ep;
+       struct qedr_qp_hwq_info sq;
+       struct qedr_qp_hwq_info rq;
+@@ -395,6 +406,7 @@ struct qedr_qp {
+       u32 id;
+       struct qedr_pd *pd;
+       enum ib_qp_type qp_type;
++      enum qedr_qp_create_type create_type;
+       struct qed_rdma_qp *qed_qp;
+       u32 qp_id;
+       u16 icid;
+@@ -437,8 +449,11 @@ struct qedr_qp {
+       /* Relevant to qps created from user space only (applications) */
+       struct qedr_userq usq;
+       struct qedr_userq urq;
+-      atomic_t refcnt;
+-      bool destroyed;
++
++      /* synchronization objects used with iwarp ep */
++      struct kref refcnt;
++      struct completion iwarp_cm_comp;
++      unsigned long iwarp_cm_flags; /* enum iwarp_cm_flags */
+ };
+ struct qedr_ah {
+@@ -531,7 +546,7 @@ struct qedr_iw_ep {
+       struct iw_cm_id *cm_id;
+       struct qedr_qp  *qp;
+       void            *qed_context;
+-      u8              during_connect;
++      struct kref     refcnt;
+ };
+ static inline
+diff --git a/drivers/infiniband/hw/qedr/qedr_iw_cm.c b/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+index 7fea74739c1f..5e9732990be5 100644
+--- a/drivers/infiniband/hw/qedr/qedr_iw_cm.c
++++ b/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+@@ -79,6 +79,27 @@ qedr_fill_sockaddr6(const struct qed_iwarp_cm_info *cm_info,
+       }
+ }
++static void qedr_iw_free_qp(struct kref *ref)
++{
++      struct qedr_qp *qp = container_of(ref, struct qedr_qp, refcnt);
++
++      kfree(qp);
++}
++
++static void
++qedr_iw_free_ep(struct kref *ref)
++{
++      struct qedr_iw_ep *ep = container_of(ref, struct qedr_iw_ep, refcnt);
++
++      if (ep->qp)
++              kref_put(&ep->qp->refcnt, qedr_iw_free_qp);
++
++      if (ep->cm_id)
++              ep->cm_id->rem_ref(ep->cm_id);
++
++      kfree(ep);
++}
++
+ static void
+ qedr_iw_mpa_request(void *context, struct qed_iwarp_cm_event_params *params)
+ {
+@@ -93,6 +114,7 @@ qedr_iw_mpa_request(void *context, struct qed_iwarp_cm_event_params *params)
+       ep->dev = dev;
+       ep->qed_context = params->ep_context;
++      kref_init(&ep->refcnt);
+       memset(&event, 0, sizeof(event));
+       event.event = IW_CM_EVENT_CONNECT_REQUEST;
+@@ -141,12 +163,10 @@ qedr_iw_close_event(void *context, struct qed_iwarp_cm_event_params *params)
+ {
+       struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
+-      if (ep->cm_id) {
++      if (ep->cm_id)
+               qedr_iw_issue_event(context, params, IW_CM_EVENT_CLOSE);
+-              ep->cm_id->rem_ref(ep->cm_id);
+-              ep->cm_id = NULL;
+-      }
++      kref_put(&ep->refcnt, qedr_iw_free_ep);
+ }
+ static void
+@@ -186,11 +206,13 @@ static void qedr_iw_disconnect_worker(struct work_struct *work)
+       struct qedr_qp *qp = ep->qp;
+       struct iw_cm_event event;
+-      if (qp->destroyed) {
+-              kfree(dwork);
+-              qedr_iw_qp_rem_ref(&qp->ibqp);
+-              return;
+-      }
++      /* The qp won't be released until we release the ep.
++       * the ep's refcnt was increased before calling this
++       * function, therefore it is safe to access qp
++       */
++      if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_DISCONNECT,
++                           &qp->iwarp_cm_flags))
++              goto out;
+       memset(&event, 0, sizeof(event));
+       event.status = dwork->status;
+@@ -204,7 +226,6 @@ static void qedr_iw_disconnect_worker(struct work_struct *work)
+       else
+               qp_params.new_state = QED_ROCE_QP_STATE_SQD;
+-      kfree(dwork);
+       if (ep->cm_id)
+               ep->cm_id->event_handler(ep->cm_id, &event);
+@@ -214,7 +235,10 @@ static void qedr_iw_disconnect_worker(struct work_struct *work)
+       dev->ops->rdma_modify_qp(dev->rdma_ctx, qp->qed_qp, &qp_params);
+-      qedr_iw_qp_rem_ref(&qp->ibqp);
++      complete(&ep->qp->iwarp_cm_comp);
++out:
++      kfree(dwork);
++      kref_put(&ep->refcnt, qedr_iw_free_ep);
+ }
+ static void
+@@ -224,13 +248,17 @@ qedr_iw_disconnect_event(void *context,
+       struct qedr_discon_work *work;
+       struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
+       struct qedr_dev *dev = ep->dev;
+-      struct qedr_qp *qp = ep->qp;
+       work = kzalloc(sizeof(*work), GFP_ATOMIC);
+       if (!work)
+               return;
+-      qedr_iw_qp_add_ref(&qp->ibqp);
++      /* We can't get a close event before disconnect, but since
++       * we're scheduling a work queue we need to make sure close
++       * won't delete the ep, so we increase the refcnt
++       */
++      kref_get(&ep->refcnt);
++
+       work->ep = ep;
+       work->event = params->event;
+       work->status = params->status;
+@@ -252,16 +280,30 @@ qedr_iw_passive_complete(void *context,
+       if ((params->status == -ECONNREFUSED) && (!ep->qp)) {
+               DP_DEBUG(dev, QEDR_MSG_IWARP,
+                        "PASSIVE connection refused releasing ep...\n");
+-              kfree(ep);
++              kref_put(&ep->refcnt, qedr_iw_free_ep);
+               return;
+       }
++      complete(&ep->qp->iwarp_cm_comp);
+       qedr_iw_issue_event(context, params, IW_CM_EVENT_ESTABLISHED);
+       if (params->status < 0)
+               qedr_iw_close_event(context, params);
+ }
++static void
++qedr_iw_active_complete(void *context,
++                      struct qed_iwarp_cm_event_params *params)
++{
++      struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
++
++      complete(&ep->qp->iwarp_cm_comp);
++      qedr_iw_issue_event(context, params, IW_CM_EVENT_CONNECT_REPLY);
++
++      if (params->status < 0)
++              kref_put(&ep->refcnt, qedr_iw_free_ep);
++}
++
+ static int
+ qedr_iw_mpa_reply(void *context, struct qed_iwarp_cm_event_params *params)
+ {
+@@ -288,27 +330,15 @@ qedr_iw_event_handler(void *context, struct qed_iwarp_cm_event_params *params)
+               qedr_iw_mpa_reply(context, params);
+               break;
+       case QED_IWARP_EVENT_PASSIVE_COMPLETE:
+-              ep->during_connect = 0;
+               qedr_iw_passive_complete(context, params);
+               break;
+-
+       case QED_IWARP_EVENT_ACTIVE_COMPLETE:
+-              ep->during_connect = 0;
+-              qedr_iw_issue_event(context,
+-                                  params,
+-                                  IW_CM_EVENT_CONNECT_REPLY);
+-              if (params->status < 0) {
+-                      struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
+-
+-                      ep->cm_id->rem_ref(ep->cm_id);
+-                      ep->cm_id = NULL;
+-              }
++              qedr_iw_active_complete(context, params);
+               break;
+       case QED_IWARP_EVENT_DISCONNECT:
+               qedr_iw_disconnect_event(context, params);
+               break;
+       case QED_IWARP_EVENT_CLOSE:
+-              ep->during_connect = 0;
+               qedr_iw_close_event(context, params);
+               break;
+       case QED_IWARP_EVENT_RQ_EMPTY:
+@@ -476,6 +506,19 @@ qedr_addr6_resolve(struct qedr_dev *dev,
+       return rc;
+ }
++struct qedr_qp *qedr_iw_load_qp(struct qedr_dev *dev, u32 qpn)
++{
++      struct qedr_qp *qp;
++
++      xa_lock(&dev->qps);
++      qp = xa_load(&dev->qps, qpn);
++      if (qp)
++              kref_get(&qp->refcnt);
++      xa_unlock(&dev->qps);
++
++      return qp;
++}
++
+ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ {
+       struct qedr_dev *dev = get_qedr_dev(cm_id->device);
+@@ -491,10 +534,6 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+       int rc = 0;
+       int i;
+-      qp = xa_load(&dev->qps, conn_param->qpn);
+-      if (unlikely(!qp))
+-              return -EINVAL;
+-
+       laddr = (struct sockaddr_in *)&cm_id->m_local_addr;
+       raddr = (struct sockaddr_in *)&cm_id->m_remote_addr;
+       laddr6 = (struct sockaddr_in6 *)&cm_id->m_local_addr;
+@@ -516,8 +555,15 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+               return -ENOMEM;
+       ep->dev = dev;
++      kref_init(&ep->refcnt);
++
++      qp = qedr_iw_load_qp(dev, conn_param->qpn);
++      if (!qp) {
++              rc = -EINVAL;
++              goto err;
++      }
++
+       ep->qp = qp;
+-      qp->ep = ep;
+       cm_id->add_ref(cm_id);
+       ep->cm_id = cm_id;
+@@ -580,16 +626,20 @@ int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+       in_params.qp = qp->qed_qp;
+       memcpy(in_params.local_mac_addr, dev->ndev->dev_addr, ETH_ALEN);
+-      ep->during_connect = 1;
++      if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_CONNECT,
++                           &qp->iwarp_cm_flags))
++              goto err; /* QP already being destroyed */
++
+       rc = dev->ops->iwarp_connect(dev->rdma_ctx, &in_params, &out_params);
+-      if (rc)
++      if (rc) {
++              complete(&qp->iwarp_cm_comp);
+               goto err;
++      }
+       return rc;
+ err:
+-      cm_id->rem_ref(cm_id);
+-      kfree(ep);
++      kref_put(&ep->refcnt, qedr_iw_free_ep);
+       return rc;
+ }
+@@ -677,18 +727,17 @@ int qedr_iw_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+       struct qedr_dev *dev = ep->dev;
+       struct qedr_qp *qp;
+       struct qed_iwarp_accept_in params;
+-      int rc;
++      int rc = 0;
+       DP_DEBUG(dev, QEDR_MSG_IWARP, "Accept on qpid=%d\n", conn_param->qpn);
+-      qp = xa_load(&dev->qps, conn_param->qpn);
++      qp = qedr_iw_load_qp(dev, conn_param->qpn);
+       if (!qp) {
+               DP_ERR(dev, "Invalid QP number %d\n", conn_param->qpn);
+               return -EINVAL;
+       }
+       ep->qp = qp;
+-      qp->ep = ep;
+       cm_id->add_ref(cm_id);
+       ep->cm_id = cm_id;
+@@ -700,15 +749,21 @@ int qedr_iw_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+       params.ird = conn_param->ird;
+       params.ord = conn_param->ord;
+-      ep->during_connect = 1;
++      if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_CONNECT,
++                           &qp->iwarp_cm_flags))
++              goto err; /* QP already destroyed */
++
+       rc = dev->ops->iwarp_accept(dev->rdma_ctx, &params);
+-      if (rc)
++      if (rc) {
++              complete(&qp->iwarp_cm_comp);
+               goto err;
++      }
+       return rc;
++
+ err:
+-      ep->during_connect = 0;
+-      cm_id->rem_ref(cm_id);
++      kref_put(&ep->refcnt, qedr_iw_free_ep);
++
+       return rc;
+ }
+@@ -731,17 +786,14 @@ void qedr_iw_qp_add_ref(struct ib_qp *ibqp)
+ {
+       struct qedr_qp *qp = get_qedr_qp(ibqp);
+-      atomic_inc(&qp->refcnt);
++      kref_get(&qp->refcnt);
+ }
+ void qedr_iw_qp_rem_ref(struct ib_qp *ibqp)
+ {
+       struct qedr_qp *qp = get_qedr_qp(ibqp);
+-      if (atomic_dec_and_test(&qp->refcnt)) {
+-              xa_erase(&qp->dev->qps, qp->qp_id);
+-              kfree(qp);
+-      }
++      kref_put(&qp->refcnt, qedr_iw_free_qp);
+ }
+ struct ib_qp *qedr_iw_get_qp(struct ib_device *ibdev, int qpn)
+diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
+index 062165935441..8b4240c1cc76 100644
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -51,6 +51,7 @@
+ #include "verbs.h"
+ #include <rdma/qedr-abi.h>
+ #include "qedr_roce_cm.h"
++#include "qedr_iw_cm.h"
+ #define QEDR_SRQ_WQE_ELEM_SIZE        sizeof(union rdma_srq_elm)
+ #define       RDMA_MAX_SGE_PER_SRQ    (4)
+@@ -1193,7 +1194,10 @@ static void qedr_set_common_qp_params(struct qedr_dev *dev,
+                                     struct ib_qp_init_attr *attrs)
+ {
+       spin_lock_init(&qp->q_lock);
+-      atomic_set(&qp->refcnt, 1);
++      if (rdma_protocol_iwarp(&dev->ibdev, 1)) {
++              kref_init(&qp->refcnt);
++              init_completion(&qp->iwarp_cm_comp);
++      }
+       qp->pd = pd;
+       qp->qp_type = attrs->qp_type;
+       qp->max_inline_data = attrs->cap.max_inline_data;
+@@ -1600,6 +1604,7 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
+       int alloc_and_init = rdma_protocol_roce(&dev->ibdev, 1);
+       int rc = -EINVAL;
++      qp->create_type = QEDR_QP_CREATE_USER;
+       memset(&ureq, 0, sizeof(ureq));
+       rc = ib_copy_from_udata(&ureq, udata, sizeof(ureq));
+       if (rc) {
+@@ -1813,6 +1818,7 @@ static int qedr_create_kernel_qp(struct qedr_dev *dev,
+       u32 n_sq_entries;
+       memset(&in_params, 0, sizeof(in_params));
++      qp->create_type = QEDR_QP_CREATE_KERNEL;
+       /* A single work request may take up to QEDR_MAX_SQ_WQE_SIZE elements in
+        * the ring. The ring should allow at least a single WR, even if the
+@@ -2445,7 +2451,7 @@ static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp,
+                       return rc;
+       }
+-      if (udata)
++      if (qp->create_type == QEDR_QP_CREATE_USER)
+               qedr_cleanup_user(dev, qp);
+       else
+               qedr_cleanup_kernel(dev, qp);
+@@ -2475,34 +2481,44 @@ int qedr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+                       qedr_modify_qp(ibqp, &attr, attr_mask, NULL);
+               }
+       } else {
+-              /* Wait for the connect/accept to complete */
+-              if (qp->ep) {
+-                      int wait_count = 1;
+-
+-                      while (qp->ep->during_connect) {
+-                              DP_DEBUG(dev, QEDR_MSG_QP,
+-                                       "Still in during connect/accept\n");
+-
+-                              msleep(100);
+-                              if (wait_count++ > 200) {
+-                                      DP_NOTICE(dev,
+-                                                "during connect timeout\n");
+-                                      break;
+-                              }
+-                      }
+-              }
++              /* If connection establishment started the WAIT_FOR_CONNECT
++               * bit will be on and we need to Wait for the establishment
++               * to complete before destroying the qp.
++               */
++              if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_CONNECT,
++                                   &qp->iwarp_cm_flags))
++                      wait_for_completion(&qp->iwarp_cm_comp);
++
++              /* If graceful disconnect started, the WAIT_FOR_DISCONNECT
++               * bit will be on, and we need to wait for the disconnect to
++               * complete before continuing. We can use the same completion,
++               * iwarp_cm_comp, since this is the only place that waits for
++               * this completion and it is sequential. In addition,
++               * disconnect can't occur before the connection is fully
++               * established, therefore if WAIT_FOR_DISCONNECT is on it
++               * means WAIT_FOR_CONNECT is also on and the completion for
++               * CONNECT already occurred.
++               */
++              if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_DISCONNECT,
++                                   &qp->iwarp_cm_flags))
++                      wait_for_completion(&qp->iwarp_cm_comp);
+       }
+       if (qp->qp_type == IB_QPT_GSI)
+               qedr_destroy_gsi_qp(dev);
++      /* We need to remove the entry from the xarray before we release the
++       * qp_id to avoid a race of the qp_id being reallocated and failing
++       * on xa_insert
++       */
++      if (rdma_protocol_iwarp(&dev->ibdev, 1))
++              xa_erase(&dev->qps, qp->qp_id);
++
+       qedr_free_qp_resources(dev, qp, udata);
+-      if (atomic_dec_and_test(&qp->refcnt) &&
+-          rdma_protocol_iwarp(&dev->ibdev, 1)) {
+-              xa_erase(&dev->qps, qp->qp_id);
+-              kfree(qp);
+-      }
++      if (rdma_protocol_iwarp(&dev->ibdev, 1))
++              qedr_iw_qp_rem_ref(&qp->ibqp);
++
+       return 0;
+ }
+-- 
+2.25.1
+
diff --git a/queue-5.4/s390-ftrace-save-traced-function-caller.patch b/queue-5.4/s390-ftrace-save-traced-function-caller.patch
new file mode 100644 (file)
index 0000000..6764e7d
--- /dev/null
@@ -0,0 +1,55 @@
+From bfc3211b9f9611b864a2f227fae89a1942fd873c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Dec 2019 13:50:23 +0100
+Subject: s390/ftrace: save traced function caller
+
+From: Vasily Gorbik <gor@linux.ibm.com>
+
+[ Upstream commit b4adfe55915d8363e244e42386d69567db1719b9 ]
+
+A typical backtrace acquired from ftraced function currently looks like
+the following (e.g. for "path_openat"):
+
+arch_stack_walk+0x15c/0x2d8
+stack_trace_save+0x50/0x68
+stack_trace_call+0x15a/0x3b8
+ftrace_graph_caller+0x0/0x1c
+0x3e0007e3c98 <- ftraced function caller (should be do_filp_open+0x7c/0xe8)
+do_open_execat+0x70/0x1b8
+__do_execve_file.isra.0+0x7d8/0x860
+__s390x_sys_execve+0x56/0x68
+system_call+0xdc/0x2d8
+
+Note random "0x3e0007e3c98" stack value as ftraced function caller. This
+value causes either imprecise unwinder result or unwinding failure.
+That "0x3e0007e3c98" comes from r14 of ftraced function stack frame, which
+it haven't had a chance to initialize since the very first instruction
+calls ftrace code ("ftrace_caller"). (ftraced function might never
+save r14 as well). Nevertheless according to s390 ABI any function
+is called with stack frame allocated for it and r14 contains return
+address. "ftrace_caller" itself is called with "brasl %r0,ftrace_caller".
+So, to fix this issue simply always save traced function caller onto
+ftraced function stack frame.
+
+Reported-by: Sven Schnelle <svens@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/mcount.S | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
+index 3431b2d5e334..f942341429b1 100644
+--- a/arch/s390/kernel/mcount.S
++++ b/arch/s390/kernel/mcount.S
+@@ -41,6 +41,7 @@ EXPORT_SYMBOL(_mcount)
+ ENTRY(ftrace_caller)
+       .globl  ftrace_regs_caller
+       .set    ftrace_regs_caller,ftrace_caller
++      stg     %r14,(__SF_GPRS+8*8)(%r15)      # save traced function caller
+       lgr     %r1,%r15
+ #if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
+       aghi    %r0,MCOUNT_RETURN_FIXUP
+-- 
+2.25.1
+
diff --git a/queue-5.4/scsi-hisi_sas-check-sas_port-before-using-it.patch b/queue-5.4/scsi-hisi_sas-check-sas_port-before-using-it.patch
new file mode 100644 (file)
index 0000000..7f4b574
--- /dev/null
@@ -0,0 +1,42 @@
+From 0ae944a6075c8200b14fd80b2716bc5856cd7d13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Nov 2019 17:30:56 +0800
+Subject: scsi: hisi_sas: Check sas_port before using it
+
+From: Xiang Chen <chenxiang66@hisilicon.com>
+
+[ Upstream commit 8c39673d5474b95374df2104dc1f65205c5278b8 ]
+
+Need to check the structure sas_port before using it.
+
+Link: https://lore.kernel.org/r/1573551059-107873-2-git-send-email-john.garry@huawei.com
+Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com>
+Signed-off-by: John Garry <john.garry@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 849335d76cf6..6f4692f0d714 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -974,12 +974,13 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
+       struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
+       struct hisi_sas_phy *phy = sas_phy->lldd_phy;
+       struct asd_sas_port *sas_port = sas_phy->port;
+-      struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
++      struct hisi_sas_port *port;
+       unsigned long flags;
+       if (!sas_port)
+               return;
++      port = to_hisi_sas_port(sas_port);
+       spin_lock_irqsave(&hisi_hba->lock, flags);
+       port->port_attached = 1;
+       port->id = phy->port_id;
+-- 
+2.25.1
+
index e44d05ebbc88a2a8caf91f631fd75f47245150f9..e6c6c8f1850afb9e871e828f449ee380d6a2472c 100644 (file)
@@ -1 +1,10 @@
 revert-cgroup-add-memory-barriers-to-plug-cgroup_rst.patch
+drm-i915-fix-port-checks-for-mst-support-on-gen-11.patch
+scsi-hisi_sas-check-sas_port-before-using-it.patch
+powerpc-powernv-avoid-re-registration-of-imc-debugfs.patch
+powerpc-xmon-restrict-when-kernel-is-locked-down.patch
+spi-dw-use-smp_mb-to-avoid-sending-spi-data-error.patch
+asoc-intel-fix-the-card-names.patch
+s390-ftrace-save-traced-function-caller.patch
+rdma-qedr-fix-qpids-xarray-api-used.patch
+rdma-qedr-fix-synchronization-methods-and-memory-lea.patch
diff --git a/queue-5.4/spi-dw-use-smp_mb-to-avoid-sending-spi-data-error.patch b/queue-5.4/spi-dw-use-smp_mb-to-avoid-sending-spi-data-error.patch
new file mode 100644 (file)
index 0000000..4a41e1b
--- /dev/null
@@ -0,0 +1,48 @@
+From d436666b964445f4eccb7d9a79f112a35de77027 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 3 Jan 2020 10:52:10 +0800
+Subject: spi: dw: use "smp_mb()" to avoid sending spi data error
+
+From: Xinwei Kong <kong.kongxinwei@hisilicon.com>
+
+[ Upstream commit bfda044533b213985bc62bd7ca96f2b984d21b80 ]
+
+Because of out-of-order execution about some CPU architecture,
+In this debug stage we find Completing spi interrupt enable ->
+prodrucing TXEI interrupt -> running "interrupt_transfer" function
+will prior to set "dw->rx and dws->rx_end" data, so this patch add
+memory barrier to enable dw->rx and dw->rx_end to be visible and
+solve to send SPI data error.
+eg:
+it will fix to this following low possibility error in testing environment
+which using SPI control to connect TPM Modules
+
+kernel: tpm tpm0: Operation Timed out
+kernel: tpm tpm0: tpm_relinquish_locality: : error -1
+
+Signed-off-by: fengsheng <fengsheng5@huawei.com>
+Signed-off-by: Xinwei Kong <kong.kongxinwei@hisilicon.com>
+Link: https://lore.kernel.org/r/1578019930-55858-1-git-send-email-kong.kongxinwei@hisilicon.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-dw.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
+index 11cac7e10663..d2ca3b357cfe 100644
+--- a/drivers/spi/spi-dw.c
++++ b/drivers/spi/spi-dw.c
+@@ -297,6 +297,9 @@ static int dw_spi_transfer_one(struct spi_controller *master,
+       dws->len = transfer->len;
+       spin_unlock_irqrestore(&dws->buf_lock, flags);
++      /* Ensure dw->rx and dw->rx_end are visible */
++      smp_mb();
++
+       spi_enable_chip(dws, 0);
+       /* Handle per transfer options for bpw and speed */
+-- 
+2.25.1
+