]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Mar 2021 13:53:17 +0000 (14:53 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Mar 2021 13:53:17 +0000 (14:53 +0100)
added patches:
arm64-module-set-plt-section-addresses-to-0x0.patch
input-elantech-fix-protocol-errors-for-some-trackpoints-in-smbus-mode.patch
mips-vdso-use-clang_flags-instead-of-filtering-out-target.patch
net-usb-qmi_wwan-support-zte-p685m-modem.patch
nvme-pci-fix-error-unwind-in-nvme_map_data.patch
nvme-pci-refactor-nvme_unmap_data.patch

queue-5.4/arm64-module-set-plt-section-addresses-to-0x0.patch [new file with mode: 0644]
queue-5.4/input-elantech-fix-protocol-errors-for-some-trackpoints-in-smbus-mode.patch [new file with mode: 0644]
queue-5.4/mips-vdso-use-clang_flags-instead-of-filtering-out-target.patch [new file with mode: 0644]
queue-5.4/net-usb-qmi_wwan-support-zte-p685m-modem.patch [new file with mode: 0644]
queue-5.4/nvme-pci-fix-error-unwind-in-nvme_map_data.patch [new file with mode: 0644]
queue-5.4/nvme-pci-refactor-nvme_unmap_data.patch [new file with mode: 0644]

diff --git a/queue-5.4/arm64-module-set-plt-section-addresses-to-0x0.patch b/queue-5.4/arm64-module-set-plt-section-addresses-to-0x0.patch
new file mode 100644 (file)
index 0000000..386d2dd
--- /dev/null
@@ -0,0 +1,39 @@
+From f5c6d0fcf90ce07ee0d686d465b19b247ebd5ed7 Mon Sep 17 00:00:00 2001
+From: Shaoying Xu <shaoyi@amazon.com>
+Date: Tue, 16 Feb 2021 18:32:34 +0000
+Subject: arm64 module: set plt* section addresses to 0x0
+
+From: Shaoying Xu <shaoyi@amazon.com>
+
+commit f5c6d0fcf90ce07ee0d686d465b19b247ebd5ed7 upstream.
+
+These plt* and .text.ftrace_trampoline sections specified for arm64 have
+non-zero addressses. Non-zero section addresses in a relocatable ELF would
+confuse GDB when it tries to compute the section offsets and it ends up
+printing wrong symbol addresses. Therefore, set them to zero, which mirrors
+the change in commit 5d8591bc0fba ("module: set ksymtab/kcrctab* section
+addresses to 0x0").
+
+Reported-by: Frank van der Linden <fllinden@amazon.com>
+Signed-off-by: Shaoying Xu <shaoyi@amazon.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210216183234.GA23876@amazon.com
+Signed-off-by: Will Deacon <will@kernel.org>
+[shaoyi@amazon.com: made same changes in arch/arm64/kernel/module.lds for 5.4]
+Signed-off-by: Shaoying Xu <shaoyi@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/module.lds |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/kernel/module.lds
++++ b/arch/arm64/kernel/module.lds
+@@ -1,5 +1,5 @@
+ SECTIONS {
+-      .plt (NOLOAD) : { BYTE(0) }
+-      .init.plt (NOLOAD) : { BYTE(0) }
+-      .text.ftrace_trampoline (NOLOAD) : { BYTE(0) }
++      .plt 0 (NOLOAD) : { BYTE(0) }
++      .init.plt 0 (NOLOAD) : { BYTE(0) }
++      .text.ftrace_trampoline 0 (NOLOAD) : { BYTE(0) }
+ }
diff --git a/queue-5.4/input-elantech-fix-protocol-errors-for-some-trackpoints-in-smbus-mode.patch b/queue-5.4/input-elantech-fix-protocol-errors-for-some-trackpoints-in-smbus-mode.patch
new file mode 100644 (file)
index 0000000..72aced0
--- /dev/null
@@ -0,0 +1,199 @@
+From e4c9062717feda88900b566463228d1c4910af6d Mon Sep 17 00:00:00 2001
+From: "jingle.wu" <jingle.wu@emc.com.tw>
+Date: Thu, 10 Dec 2020 23:49:16 -0800
+Subject: Input: elantech - fix protocol errors for some trackpoints in SMBus mode
+
+From: jingle.wu <jingle.wu@emc.com.tw>
+
+commit e4c9062717feda88900b566463228d1c4910af6d upstream.
+
+There are some version of Elan trackpads that send incorrect data when
+in SMbus mode, unless they are switched to use 0x5f reports instead of
+standard 0x5e. This patch implements querying device to retrieve chips
+identifying data, and switching it, when needed to the alternative
+report.
+
+Signed-off-by: Jingle Wu <jingle.wu@emc.com.tw>
+Link: https://lore.kernel.org/r/20201211071531.32413-1-jingle.wu@emc.com.tw
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/mouse/elantech.c |   99 ++++++++++++++++++++++++++++++++++++++++-
+ drivers/input/mouse/elantech.h |    4 +
+ 2 files changed, 101 insertions(+), 2 deletions(-)
+
+--- a/drivers/input/mouse/elantech.c
++++ b/drivers/input/mouse/elantech.c
+@@ -90,6 +90,47 @@ static int elantech_ps2_command(struct p
+ }
+ /*
++ * Send an Elantech style special command to read 3 bytes from a register
++ */
++static int elantech_read_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
++{
++      if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
++          elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
++          elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
++          elantech_ps2_command(psmouse, NULL, reg) ||
++          elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
++              psmouse_err(psmouse,
++                          "failed to read register %#02x\n", reg);
++              return -EIO;
++      }
++
++      return 0;
++}
++
++/*
++ * Send an Elantech style special command to write a register with a parameter
++ */
++static int elantech_write_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
++{
++      if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
++          elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
++          elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
++          elantech_ps2_command(psmouse, NULL, reg) ||
++          elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
++          elantech_ps2_command(psmouse, NULL, param[0]) ||
++          elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
++          elantech_ps2_command(psmouse, NULL, param[1]) ||
++          elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
++              psmouse_err(psmouse,
++                          "failed to write register %#02x with value %#02x%#02x\n",
++                          reg, param[0], param[1]);
++              return -EIO;
++      }
++
++      return 0;
++}
++
++/*
+  * Send an Elantech style special command to read a value from a register
+  */
+ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
+@@ -1530,18 +1571,34 @@ static const struct dmi_system_id no_hw_
+ };
+ /*
++ * Change Report id 0x5E to 0x5F.
++ */
++static int elantech_change_report_id(struct psmouse *psmouse)
++{
++      unsigned char param[2] = { 0x10, 0x03 };
++
++      if (elantech_write_reg_params(psmouse, 0x7, param) ||
++          elantech_read_reg_params(psmouse, 0x7, param) ||
++          param[0] != 0x10 || param[1] != 0x03) {
++              psmouse_err(psmouse, "Unable to change report ID to 0x5f.\n");
++              return -EIO;
++      }
++
++      return 0;
++}
++/*
+  * determine hardware version and set some properties according to it.
+  */
+ static int elantech_set_properties(struct elantech_device_info *info)
+ {
+       /* This represents the version of IC body. */
+-      int ver = (info->fw_version & 0x0f0000) >> 16;
++      info->ic_version = (info->fw_version & 0x0f0000) >> 16;
+       /* Early version of Elan touchpads doesn't obey the rule. */
+       if (info->fw_version < 0x020030 || info->fw_version == 0x020600)
+               info->hw_version = 1;
+       else {
+-              switch (ver) {
++              switch (info->ic_version) {
+               case 2:
+               case 4:
+                       info->hw_version = 2;
+@@ -1557,6 +1614,11 @@ static int elantech_set_properties(struc
+               }
+       }
++      /* Get information pattern for hw_version 4 */
++      info->pattern = 0x00;
++      if (info->ic_version == 0x0f && (info->fw_version & 0xff) <= 0x02)
++              info->pattern = info->fw_version & 0xff;
++
+       /* decide which send_cmd we're gonna use early */
+       info->send_cmd = info->hw_version >= 3 ? elantech_send_cmd :
+                                                synaptics_send_cmd;
+@@ -1598,6 +1660,7 @@ static int elantech_query_info(struct ps
+ {
+       unsigned char param[3];
+       unsigned char traces;
++      unsigned char ic_body[3];
+       memset(info, 0, sizeof(*info));
+@@ -1640,6 +1703,21 @@ static int elantech_query_info(struct ps
+                            info->samples[2]);
+       }
++      if (info->pattern > 0x00 && info->ic_version == 0xf) {
++              if (info->send_cmd(psmouse, ETP_ICBODY_QUERY, ic_body)) {
++                      psmouse_err(psmouse, "failed to query ic body\n");
++                      return -EINVAL;
++              }
++              info->ic_version = be16_to_cpup((__be16 *)ic_body);
++              psmouse_info(psmouse,
++                           "Elan ic body: %#04x, current fw version: %#02x\n",
++                           info->ic_version, ic_body[2]);
++      }
++
++      info->product_id = be16_to_cpup((__be16 *)info->samples);
++      if (info->pattern == 0x00)
++              info->product_id &= 0xff;
++
+       if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
+               /*
+                * This module has a bug which makes absolute mode
+@@ -1654,6 +1732,23 @@ static int elantech_query_info(struct ps
+       /* The MSB indicates the presence of the trackpoint */
+       info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
++      if (info->has_trackpoint && info->ic_version == 0x0011 &&
++          (info->product_id == 0x08 || info->product_id == 0x09 ||
++           info->product_id == 0x0d || info->product_id == 0x0e)) {
++              /*
++               * This module has a bug which makes trackpoint in SMBus
++               * mode return invalid data unless trackpoint is switched
++               * from using 0x5e reports to 0x5f. If we are not able to
++               * make the switch, let's abort initialization so we'll be
++               * using standard PS/2 protocol.
++               */
++              if (elantech_change_report_id(psmouse)) {
++                      psmouse_info(psmouse,
++                                   "Trackpoint report is broken, forcing standard PS/2 protocol\n");
++                      return -ENODEV;
++              }
++      }
++
+       info->x_res = 31;
+       info->y_res = 31;
+       if (info->hw_version == 4) {
+--- a/drivers/input/mouse/elantech.h
++++ b/drivers/input/mouse/elantech.h
+@@ -18,6 +18,7 @@
+ #define ETP_CAPABILITIES_QUERY                0x02
+ #define ETP_SAMPLE_QUERY              0x03
+ #define ETP_RESOLUTION_QUERY          0x04
++#define ETP_ICBODY_QUERY              0x05
+ /*
+  * Command values for register reading or writing
+@@ -140,7 +141,10 @@ struct elantech_device_info {
+       unsigned char samples[3];
+       unsigned char debug;
+       unsigned char hw_version;
++      unsigned char pattern;
+       unsigned int fw_version;
++      unsigned int ic_version;
++      unsigned int product_id;
+       unsigned int x_min;
+       unsigned int y_min;
+       unsigned int x_max;
diff --git a/queue-5.4/mips-vdso-use-clang_flags-instead-of-filtering-out-target.patch b/queue-5.4/mips-vdso-use-clang_flags-instead-of-filtering-out-target.patch
new file mode 100644 (file)
index 0000000..aee2a06
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Thu Mar  4 02:51:17 PM CET 2021
+From: Nathan Chancellor <natechancellor@gmail.com>
+Date: Fri, 15 Jan 2021 12:26:22 -0700
+Subject: MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
+
+From: Nathan Chancellor <natechancellor@gmail.com>
+
+commit 76d7fff22be3e4185ee5f9da2eecbd8188e76b2c upstream.
+
+Commit ee67855ecd9d ("MIPS: vdso: Allow clang's --target flag in VDSO
+cflags") allowed the '--target=' flag from the main Makefile to filter
+through to the vDSO. However, it did not bring any of the other clang
+specific flags for controlling the integrated assembler and the GNU
+tools locations (--prefix=, --gcc-toolchain=, and -no-integrated-as).
+Without these, we will get a warning (visible with tinyconfig):
+
+arch/mips/vdso/elf.S:14:1: warning: DWARF2 only supports one section per
+compilation unit
+.pushsection .note.Linux, "a",@note ; .balign 4 ; .long 2f - 1f ; .long
+4484f - 3f ; .long 0 ; 1:.asciz "Linux" ; 2:.balign 4 ; 3:
+^
+arch/mips/vdso/elf.S:34:2: warning: DWARF2 only supports one section per
+compilation unit
+ .section .mips_abiflags, "a"
+ ^
+
+All of these flags are bundled up under CLANG_FLAGS in the main Makefile
+and exported so that they can be added to Makefiles that set their own
+CFLAGS. Use this value instead of filtering out '--target=' so there is
+no warning and all of the tools are properly used.
+
+Cc: stable@vger.kernel.org
+Fixes: ee67855ecd9d ("MIPS: vdso: Allow clang's --target flag in VDSO cflags")
+Link: https://github.com/ClangBuiltLinux/linux/issues/1256
+Reported-by: Anders Roxell <anders.roxell@linaro.org>
+Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
+Tested-by: Anders Roxell <anders.roxell@linaro.org>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+[nc: Fix conflict due to lack of 99570c3da96a in 5.4]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/mips/vdso/Makefile |    5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/arch/mips/vdso/Makefile
++++ b/arch/mips/vdso/Makefile
+@@ -16,12 +16,9 @@ ccflags-vdso := \
+       $(filter -march=%,$(KBUILD_CFLAGS)) \
+       $(filter -m%-float,$(KBUILD_CFLAGS)) \
+       $(filter -mno-loongson-%,$(KBUILD_CFLAGS)) \
++      $(CLANG_FLAGS) \
+       -D__VDSO__
+-ifdef CONFIG_CC_IS_CLANG
+-ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS))
+-endif
+-
+ #
+ # The -fno-jump-tables flag only prevents the compiler from generating
+ # jump tables but does not prevent the compiler from emitting absolute
diff --git a/queue-5.4/net-usb-qmi_wwan-support-zte-p685m-modem.patch b/queue-5.4/net-usb-qmi_wwan-support-zte-p685m-modem.patch
new file mode 100644 (file)
index 0000000..3acdb85
--- /dev/null
@@ -0,0 +1,65 @@
+From 88eee9b7b42e69fb622ddb3ff6f37e8e4347f5b2 Mon Sep 17 00:00:00 2001
+From: Lech Perczak <lech.perczak@gmail.com>
+Date: Tue, 23 Feb 2021 19:34:56 +0100
+Subject: net: usb: qmi_wwan: support ZTE P685M modem
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lech Perczak <lech.perczak@gmail.com>
+
+commit 88eee9b7b42e69fb622ddb3ff6f37e8e4347f5b2 upstream.
+
+Now that interface 3 in "option" driver is no longer mapped, add device
+ID matching it to qmi_wwan.
+
+The modem is used inside ZTE MF283+ router and carriers identify it as
+such.
+Interface mapping is:
+0: QCDM, 1: AT (PCUI), 2: AT (Modem), 3: QMI, 4: ADB
+
+T:  Bus=02 Lev=02 Prnt=02 Port=05 Cnt=01 Dev#=  3 Spd=480  MxCh= 0
+D:  Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
+P:  Vendor=19d2 ProdID=1275 Rev=f0.00
+S:  Manufacturer=ZTE,Incorporated
+S:  Product=ZTE Technologies MSM
+S:  SerialNumber=P685M510ZTED0000CP&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&0
+C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA
+I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E:  Ad=83(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
+E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E:  Ad=85(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
+E:  Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
+E:  Ad=87(I) Atr=03(Int.) MxPS=   8 Ivl=32ms
+E:  Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none)
+E:  Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E:  Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+
+Acked-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Lech Perczak <lech.perczak@gmail.com>
+Link: https://lore.kernel.org/r/20210223183456.6377-1-lech.perczak@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/qmi_wwan.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -1280,6 +1280,7 @@ static const struct usb_device_id produc
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1270, 5)},    /* ZTE MF667 */
++      {QMI_FIXED_INTF(0x19d2, 0x1275, 3)},    /* ZTE P685M */
+       {QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1402, 2)},    /* ZTE MF60 */
+       {QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
diff --git a/queue-5.4/nvme-pci-fix-error-unwind-in-nvme_map_data.patch b/queue-5.4/nvme-pci-fix-error-unwind-in-nvme_map_data.patch
new file mode 100644 (file)
index 0000000..a73e875
--- /dev/null
@@ -0,0 +1,109 @@
+From foo@baz Thu Mar  4 02:41:47 PM CET 2021
+From: Marc Orr <marcorr@google.com>
+Date: Tue,  2 Mar 2021 17:39:11 +0000
+Subject: nvme-pci: fix error unwind in nvme_map_data
+To: stable@vger.kernel.org
+Cc: Christoph Hellwig <hch@lst.de>, Marc Orr <marcorr@google.com>, Keith Busch <kbusch@kernel.org>
+Message-ID: <20210302173911.12044-2-marcorr@google.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit fa0732168fa1369dd089e5b06d6158a68229f7b7 upstream.
+
+Properly unwind step by step using refactored helpers from nvme_unmap_data
+to avoid a potential double dma_unmap on a mapping failure.
+
+Fixes: 7fe07d14f71f ("nvme-pci: merge nvme_free_iod into nvme_unmap_data")
+Reported-by: Marc Orr <marcorr@google.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Marc Orr <marcorr@google.com>
+Signed-off-by: Marc Orr <marcorr@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/pci.c |   28 ++++++++++++++++++----------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -669,7 +669,7 @@ static blk_status_t nvme_pci_setup_prps(
+                       __le64 *old_prp_list = prp_list;
+                       prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma);
+                       if (!prp_list)
+-                              return BLK_STS_RESOURCE;
++                              goto free_prps;
+                       list[iod->npages++] = prp_list;
+                       prp_list[0] = old_prp_list[i - 1];
+                       old_prp_list[i - 1] = cpu_to_le64(prp_dma);
+@@ -689,14 +689,14 @@ static blk_status_t nvme_pci_setup_prps(
+               dma_addr = sg_dma_address(sg);
+               dma_len = sg_dma_len(sg);
+       }
+-
+ done:
+       cmnd->dptr.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
+       cmnd->dptr.prp2 = cpu_to_le64(iod->first_dma);
+-
+       return BLK_STS_OK;
+-
+- bad_sgl:
++free_prps:
++      nvme_free_prps(dev, req);
++      return BLK_STS_RESOURCE;
++bad_sgl:
+       WARN(DO_ONCE(nvme_print_sgl, iod->sg, iod->nents),
+                       "Invalid SGL for payload:%d nents:%d\n",
+                       blk_rq_payload_bytes(req), iod->nents);
+@@ -768,7 +768,7 @@ static blk_status_t nvme_pci_setup_sgls(
+                       sg_list = dma_pool_alloc(pool, GFP_ATOMIC, &sgl_dma);
+                       if (!sg_list)
+-                              return BLK_STS_RESOURCE;
++                              goto free_sgls;
+                       i = 0;
+                       nvme_pci_iod_list(req)[iod->npages++] = sg_list;
+@@ -781,6 +781,9 @@ static blk_status_t nvme_pci_setup_sgls(
+       } while (--entries > 0);
+       return BLK_STS_OK;
++free_sgls:
++      nvme_free_sgls(dev, req);
++      return BLK_STS_RESOURCE;
+ }
+ static blk_status_t nvme_setup_prp_simple(struct nvme_dev *dev,
+@@ -849,7 +852,7 @@ static blk_status_t nvme_map_data(struct
+       sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
+       iod->nents = blk_rq_map_sg(req->q, req, iod->sg);
+       if (!iod->nents)
+-              goto out;
++              goto out_free_sg;
+       if (is_pci_p2pdma_page(sg_page(iod->sg)))
+               nr_mapped = pci_p2pdma_map_sg_attrs(dev->dev, iod->sg,
+@@ -858,16 +861,21 @@ static blk_status_t nvme_map_data(struct
+               nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents,
+                                            rq_dma_dir(req), DMA_ATTR_NO_WARN);
+       if (!nr_mapped)
+-              goto out;
++              goto out_free_sg;
+       iod->use_sgl = nvme_pci_use_sgls(dev, req);
+       if (iod->use_sgl)
+               ret = nvme_pci_setup_sgls(dev, req, &cmnd->rw, nr_mapped);
+       else
+               ret = nvme_pci_setup_prps(dev, req, &cmnd->rw);
+-out:
+       if (ret != BLK_STS_OK)
+-              nvme_unmap_data(dev, req);
++              goto out_unmap_sg;
++      return BLK_STS_OK;
++
++out_unmap_sg:
++      nvme_unmap_sg(dev, req);
++out_free_sg:
++      mempool_free(iod->sg, dev->iod_mempool);
+       return ret;
+ }
diff --git a/queue-5.4/nvme-pci-refactor-nvme_unmap_data.patch b/queue-5.4/nvme-pci-refactor-nvme_unmap_data.patch
new file mode 100644 (file)
index 0000000..a096544
--- /dev/null
@@ -0,0 +1,126 @@
+From foo@baz Thu Mar  4 02:41:47 PM CET 2021
+From: Marc Orr <marcorr@google.com>
+Date: Tue,  2 Mar 2021 17:39:10 +0000
+Subject: nvme-pci: refactor nvme_unmap_data
+To: stable@vger.kernel.org
+Cc: Christoph Hellwig <hch@lst.de>, Keith Busch <kbusch@kernel.org>, Marc Orr <marcorr@google.com>
+Message-ID: <20210302173911.12044-1-marcorr@google.com>
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 9275c206f88e5c49cb3e71932c81c8561083db9e upstream.
+
+Split out three helpers from nvme_unmap_data that will allow finer grained
+unwinding from nvme_map_data.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Marc Orr <marcorr@google.com>
+Signed-off-by: Marc Orr <marcorr@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/pci.c |   77 ++++++++++++++++++++++++++++++------------------
+ 1 file changed, 49 insertions(+), 28 deletions(-)
+
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -528,50 +528,71 @@ static inline bool nvme_pci_use_sgls(str
+       return true;
+ }
+-static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
++static void nvme_free_prps(struct nvme_dev *dev, struct request *req)
+ {
+-      struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+       const int last_prp = dev->ctrl.page_size / sizeof(__le64) - 1;
+-      dma_addr_t dma_addr = iod->first_dma, next_dma_addr;
++      struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
++      dma_addr_t dma_addr = iod->first_dma;
+       int i;
+-      if (iod->dma_len) {
+-              dma_unmap_page(dev->dev, dma_addr, iod->dma_len,
+-                             rq_dma_dir(req));
+-              return;
++      for (i = 0; i < iod->npages; i++) {
++              __le64 *prp_list = nvme_pci_iod_list(req)[i];
++              dma_addr_t next_dma_addr = le64_to_cpu(prp_list[last_prp]);
++
++              dma_pool_free(dev->prp_page_pool, prp_list, dma_addr);
++              dma_addr = next_dma_addr;
+       }
+-      WARN_ON_ONCE(!iod->nents);
++}
+-      if (is_pci_p2pdma_page(sg_page(iod->sg)))
+-              pci_p2pdma_unmap_sg(dev->dev, iod->sg, iod->nents,
+-                                  rq_dma_dir(req));
+-      else
+-              dma_unmap_sg(dev->dev, iod->sg, iod->nents, rq_dma_dir(req));
++static void nvme_free_sgls(struct nvme_dev *dev, struct request *req)
++{
++      const int last_sg = SGES_PER_PAGE - 1;
++      struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
++      dma_addr_t dma_addr = iod->first_dma;
++      int i;
++      for (i = 0; i < iod->npages; i++) {
++              struct nvme_sgl_desc *sg_list = nvme_pci_iod_list(req)[i];
++              dma_addr_t next_dma_addr = le64_to_cpu((sg_list[last_sg]).addr);
+-      if (iod->npages == 0)
+-              dma_pool_free(dev->prp_small_pool, nvme_pci_iod_list(req)[0],
+-                      dma_addr);
++              dma_pool_free(dev->prp_page_pool, sg_list, dma_addr);
++              dma_addr = next_dma_addr;
++      }
+-      for (i = 0; i < iod->npages; i++) {
+-              void *addr = nvme_pci_iod_list(req)[i];
++}
+-              if (iod->use_sgl) {
+-                      struct nvme_sgl_desc *sg_list = addr;
++static void nvme_unmap_sg(struct nvme_dev *dev, struct request *req)
++{
++      struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+-                      next_dma_addr =
+-                          le64_to_cpu((sg_list[SGES_PER_PAGE - 1]).addr);
+-              } else {
+-                      __le64 *prp_list = addr;
++      if (is_pci_p2pdma_page(sg_page(iod->sg)))
++              pci_p2pdma_unmap_sg(dev->dev, iod->sg, iod->nents,
++                                  rq_dma_dir(req));
++      else
++              dma_unmap_sg(dev->dev, iod->sg, iod->nents, rq_dma_dir(req));
++}
+-                      next_dma_addr = le64_to_cpu(prp_list[last_prp]);
+-              }
++static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
++{
++      struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+-              dma_pool_free(dev->prp_page_pool, addr, dma_addr);
+-              dma_addr = next_dma_addr;
++      if (iod->dma_len) {
++              dma_unmap_page(dev->dev, iod->first_dma, iod->dma_len,
++                             rq_dma_dir(req));
++              return;
+       }
++      WARN_ON_ONCE(!iod->nents);
++
++      nvme_unmap_sg(dev, req);
++      if (iod->npages == 0)
++              dma_pool_free(dev->prp_small_pool, nvme_pci_iod_list(req)[0],
++                            iod->first_dma);
++      else if (iod->use_sgl)
++              nvme_free_sgls(dev, req);
++      else
++              nvme_free_prps(dev, req);
+       mempool_free(iod->sg, dev->iod_mempool);
+ }