]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.5-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Feb 2020 14:47:52 +0000 (15:47 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Feb 2020 14:47:52 +0000 (15:47 +0100)
added patches:
alsa-hda-realtek-apply-quirk-for-msi-gp63-too.patch
alsa-hda-realtek-apply-quirk-for-yet-another-msi-laptop.patch
alsa-hda-use-scnprintf-for-printing-texts-for-sysfs-procfs.patch
asoc-codec2codec-avoid-invalid-double-free-of-pcm-runtime.patch
asoc-sun8i-codec-fix-setting-dai-data-format.patch
btrfs-don-t-set-path-leave_spinning-for-truncate.patch
btrfs-fix-race-between-shrinking-truncate-and-fiemap.patch
btrfs-handle-logged-extent-failure-properly.patch
ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_messaging.patch
ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch
iommu-qcom-fix-bogus-detach-logic.patch
iommu-vt-d-add-attach_deferred-helper.patch
iommu-vt-d-do-deferred-attachment-in-iommu_need_mapping.patch
iommu-vt-d-move-deferred-device-attachment-into-helper-function.patch
iommu-vt-d-remove-deferred_attach_domain.patch
iommu-vt-d-simplify-check-in-identity_mapping.patch
tpm-initialize-crypto_id-of-allocated_banks-to-hash_algo__last.patch
tpm-revert-tpm_tis_spi_mod.ko-to-tpm_tis_spi.ko.patch

19 files changed:
queue-5.5/alsa-hda-realtek-apply-quirk-for-msi-gp63-too.patch [new file with mode: 0644]
queue-5.5/alsa-hda-realtek-apply-quirk-for-yet-another-msi-laptop.patch [new file with mode: 0644]
queue-5.5/alsa-hda-use-scnprintf-for-printing-texts-for-sysfs-procfs.patch [new file with mode: 0644]
queue-5.5/asoc-codec2codec-avoid-invalid-double-free-of-pcm-runtime.patch [new file with mode: 0644]
queue-5.5/asoc-sun8i-codec-fix-setting-dai-data-format.patch [new file with mode: 0644]
queue-5.5/btrfs-don-t-set-path-leave_spinning-for-truncate.patch [new file with mode: 0644]
queue-5.5/btrfs-fix-race-between-shrinking-truncate-and-fiemap.patch [new file with mode: 0644]
queue-5.5/btrfs-handle-logged-extent-failure-properly.patch [new file with mode: 0644]
queue-5.5/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_messaging.patch [new file with mode: 0644]
queue-5.5/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch [new file with mode: 0644]
queue-5.5/iommu-qcom-fix-bogus-detach-logic.patch [new file with mode: 0644]
queue-5.5/iommu-vt-d-add-attach_deferred-helper.patch [new file with mode: 0644]
queue-5.5/iommu-vt-d-do-deferred-attachment-in-iommu_need_mapping.patch [new file with mode: 0644]
queue-5.5/iommu-vt-d-move-deferred-device-attachment-into-helper-function.patch [new file with mode: 0644]
queue-5.5/iommu-vt-d-remove-deferred_attach_domain.patch [new file with mode: 0644]
queue-5.5/iommu-vt-d-simplify-check-in-identity_mapping.patch [new file with mode: 0644]
queue-5.5/series [new file with mode: 0644]
queue-5.5/tpm-initialize-crypto_id-of-allocated_banks-to-hash_algo__last.patch [new file with mode: 0644]
queue-5.5/tpm-revert-tpm_tis_spi_mod.ko-to-tpm_tis_spi.ko.patch [new file with mode: 0644]

diff --git a/queue-5.5/alsa-hda-realtek-apply-quirk-for-msi-gp63-too.patch b/queue-5.5/alsa-hda-realtek-apply-quirk-for-msi-gp63-too.patch
new file mode 100644 (file)
index 0000000..ebe58a4
--- /dev/null
@@ -0,0 +1,32 @@
+From a655e2b107d463ce2745188ce050d07daed09a71 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 17 Feb 2020 16:19:47 +0100
+Subject: ALSA: hda/realtek - Apply quirk for MSI GP63, too
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit a655e2b107d463ce2745188ce050d07daed09a71 upstream.
+
+The same quirk that was applied to MSI GL73 is needed for MSI GP63,
+too.  Adding the entry with the SSID 1462:1228.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=206503
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200217151947.17528-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882
+       SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
++      SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+       SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
diff --git a/queue-5.5/alsa-hda-realtek-apply-quirk-for-yet-another-msi-laptop.patch b/queue-5.5/alsa-hda-realtek-apply-quirk-for-yet-another-msi-laptop.patch
new file mode 100644 (file)
index 0000000..58f95fb
--- /dev/null
@@ -0,0 +1,32 @@
+From cc5049ae4d457194796f854eb2e38b9727ad8c2d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 18 Feb 2020 09:09:15 +0100
+Subject: ALSA: hda/realtek - Apply quirk for yet another MSI laptop
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit cc5049ae4d457194796f854eb2e38b9727ad8c2d upstream.
+
+MSI GP65 laptop with SSID 1462:1293 requires the same quirk as other
+MSI models.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204159
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200218080915.3433-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2449,6 +2449,7 @@ static const struct snd_pci_quirk alc882
+       SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
++      SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+       SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
diff --git a/queue-5.5/alsa-hda-use-scnprintf-for-printing-texts-for-sysfs-procfs.patch b/queue-5.5/alsa-hda-use-scnprintf-for-printing-texts-for-sysfs-procfs.patch
new file mode 100644 (file)
index 0000000..749c465
--- /dev/null
@@ -0,0 +1,82 @@
+From 44eeb081b8630bb3ad3cd381d1ae1831463e48bb Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 18 Feb 2020 10:14:09 +0100
+Subject: ALSA: hda: Use scnprintf() for printing texts for sysfs/procfs
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 44eeb081b8630bb3ad3cd381d1ae1831463e48bb upstream.
+
+Some code in HD-audio driver calls snprintf() in a loop and still
+expects that the return value were actually written size, while
+snprintf() returns the expected would-be length instead.  When the
+given buffer limit were small, this leads to a buffer overflow.
+
+Use scnprintf() for addressing those issues.  It returns the actually
+written size unlike snprintf().
+
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200218091409.27162-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/hda/hdmi_chmap.c    |    2 +-
+ sound/pci/hda/hda_codec.c |    2 +-
+ sound/pci/hda/hda_eld.c   |    2 +-
+ sound/pci/hda/hda_sysfs.c |    4 ++--
+ 4 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/sound/hda/hdmi_chmap.c
++++ b/sound/hda/hdmi_chmap.c
+@@ -250,7 +250,7 @@ void snd_hdac_print_channel_allocation(i
+       for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
+               if (spk_alloc & (1 << i))
+-                      j += snprintf(buf + j, buflen - j,  " %s",
++                      j += scnprintf(buf + j, buflen - j,  " %s",
+                                       cea_speaker_allocation_names[i]);
+       }
+       buf[j] = '\0';  /* necessary when j == 0 */
+--- a/sound/pci/hda/hda_codec.c
++++ b/sound/pci/hda/hda_codec.c
+@@ -4019,7 +4019,7 @@ void snd_print_pcm_bits(int pcm, char *b
+       for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
+               if (pcm & (AC_SUPPCM_BITS_8 << i))
+-                      j += snprintf(buf + j, buflen - j,  " %d", bits[i]);
++                      j += scnprintf(buf + j, buflen - j,  " %d", bits[i]);
+       buf[j] = '\0'; /* necessary when j == 0 */
+ }
+--- a/sound/pci/hda/hda_eld.c
++++ b/sound/pci/hda/hda_eld.c
+@@ -360,7 +360,7 @@ static void hdmi_print_pcm_rates(int pcm
+       for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
+               if (pcm & (1 << i))
+-                      j += snprintf(buf + j, buflen - j,  " %d",
++                      j += scnprintf(buf + j, buflen - j,  " %d",
+                               alsa_rates[i]);
+       buf[j] = '\0'; /* necessary when j == 0 */
+--- a/sound/pci/hda/hda_sysfs.c
++++ b/sound/pci/hda/hda_sysfs.c
+@@ -222,7 +222,7 @@ static ssize_t init_verbs_show(struct de
+       int i, len = 0;
+       mutex_lock(&codec->user_mutex);
+       snd_array_for_each(&codec->init_verbs, i, v) {
+-              len += snprintf(buf + len, PAGE_SIZE - len,
++              len += scnprintf(buf + len, PAGE_SIZE - len,
+                               "0x%02x 0x%03x 0x%04x\n",
+                               v->nid, v->verb, v->param);
+       }
+@@ -272,7 +272,7 @@ static ssize_t hints_show(struct device
+       int i, len = 0;
+       mutex_lock(&codec->user_mutex);
+       snd_array_for_each(&codec->hints, i, hint) {
+-              len += snprintf(buf + len, PAGE_SIZE - len,
++              len += scnprintf(buf + len, PAGE_SIZE - len,
+                               "%s = %s\n", hint->key, hint->val);
+       }
+       mutex_unlock(&codec->user_mutex);
diff --git a/queue-5.5/asoc-codec2codec-avoid-invalid-double-free-of-pcm-runtime.patch b/queue-5.5/asoc-codec2codec-avoid-invalid-double-free-of-pcm-runtime.patch
new file mode 100644 (file)
index 0000000..b6bb3d3
--- /dev/null
@@ -0,0 +1,36 @@
+From b6570fdb96edf45bcf71884bd2644bd73d348d1a Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Thu, 13 Feb 2020 00:11:44 -0600
+Subject: ASoC: codec2codec: avoid invalid/double-free of pcm runtime
+
+From: Samuel Holland <samuel@sholland.org>
+
+commit b6570fdb96edf45bcf71884bd2644bd73d348d1a upstream.
+
+The PCM runtime was freed during PMU in the case that the event hook
+encountered an error. However, it is also unconditionally freed during
+PMD. Avoid a double-free by dropping the call to kfree in the PMU hook.
+
+Fixes: a72706ed8208 ("ASoC: codec2codec: remove ephemeral variables")
+Cc: stable@vger.kernel.org
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Link: https://lore.kernel.org/r/20200213061147.29386-2-samuel@sholland.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/soc-dapm.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/sound/soc/soc-dapm.c
++++ b/sound/soc/soc-dapm.c
+@@ -3888,9 +3888,6 @@ snd_soc_dai_link_event_pre_pmu(struct sn
+       runtime->rate = params_rate(params);
+ out:
+-      if (ret < 0)
+-              kfree(runtime);
+-
+       kfree(params);
+       return ret;
+ }
diff --git a/queue-5.5/asoc-sun8i-codec-fix-setting-dai-data-format.patch b/queue-5.5/asoc-sun8i-codec-fix-setting-dai-data-format.patch
new file mode 100644 (file)
index 0000000..3bb65c9
--- /dev/null
@@ -0,0 +1,43 @@
+From 96781fd941b39e1f78098009344ebcd7af861c67 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Mon, 17 Feb 2020 00:42:22 -0600
+Subject: ASoC: sun8i-codec: Fix setting DAI data format
+
+From: Samuel Holland <samuel@sholland.org>
+
+commit 96781fd941b39e1f78098009344ebcd7af861c67 upstream.
+
+Use the correct mask for this two-bit field. This fixes setting the DAI
+data format to RIGHT_J or DSP_A.
+
+Fixes: 36c684936fae ("ASoC: Add sun8i digital audio codec")
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Acked-by: Chen-Yu Tsai <wens@csie.org>
+Cc: stable@kernel.org
+Link: https://lore.kernel.org/r/20200217064250.15516-7-samuel@sholland.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/sunxi/sun8i-codec.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/sunxi/sun8i-codec.c
++++ b/sound/soc/sunxi/sun8i-codec.c
+@@ -80,6 +80,7 @@
+ #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK                GENMASK(15, 12)
+ #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK                GENMASK(11, 8)
++#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2)
+ #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4)
+ #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6)
+ #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9)
+@@ -241,7 +242,7 @@ static int sun8i_set_fmt(struct snd_soc_
+               return -EINVAL;
+       }
+       regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
+-                         BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT),
++                         SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
+                          value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
+       return 0;
diff --git a/queue-5.5/btrfs-don-t-set-path-leave_spinning-for-truncate.patch b/queue-5.5/btrfs-don-t-set-path-leave_spinning-for-truncate.patch
new file mode 100644 (file)
index 0000000..2d592a6
--- /dev/null
@@ -0,0 +1,79 @@
+From 52e29e331070cd7d52a64cbf1b0958212a340e28 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Fri, 17 Jan 2020 09:02:20 -0500
+Subject: btrfs: don't set path->leave_spinning for truncate
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 52e29e331070cd7d52a64cbf1b0958212a340e28 upstream.
+
+The only time we actually leave the path spinning is if we're truncating
+a small amount and don't actually free an extent, which is not a common
+occurrence.  We have to set the path blocking in order to add the
+delayed ref anyway, so the first extent we find we set the path to
+blocking and stay blocking for the duration of the operation.  With the
+upcoming file extent map stuff there will be another case that we have
+to have the path blocking, so just swap to blocking always.
+
+Note: this patch also fixes a warning after 28553fa992cb ("Btrfs: fix
+race between shrinking truncate and fiemap") got merged that inserts
+extent locks around truncation so the path must not leave spinning locks
+after btrfs_search_slot.
+
+  [70.794783] BUG: sleeping function called from invalid context at mm/slab.h:565
+  [70.794834] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1141, name: rsync
+  [70.794863] 5 locks held by rsync/1141:
+  [70.794876]  #0: ffff888417b9c408 (sb_writers#17){.+.+}, at: mnt_want_write+0x20/0x50
+  [70.795030]  #1: ffff888428de28e8 (&type->i_mutex_dir_key#13/1){+.+.}, at: lock_rename+0xf1/0x100
+  [70.795051]  #2: ffff888417b9c608 (sb_internal#2){.+.+}, at: start_transaction+0x394/0x560
+  [70.795124]  #3: ffff888403081768 (btrfs-fs-01){++++}, at: btrfs_try_tree_write_lock+0x2f/0x160
+  [70.795203]  #4: ffff888403086568 (btrfs-fs-00){++++}, at: btrfs_try_tree_write_lock+0x2f/0x160
+  [70.795222] CPU: 5 PID: 1141 Comm: rsync Not tainted 5.6.0-rc2-backup+ #2
+  [70.795362] Call Trace:
+  [70.795374]  dump_stack+0x71/0xa0
+  [70.795445]  ___might_sleep.part.96.cold.106+0xa6/0xb6
+  [70.795459]  kmem_cache_alloc+0x1d3/0x290
+  [70.795471]  alloc_extent_state+0x22/0x1c0
+  [70.795544]  __clear_extent_bit+0x3ba/0x580
+  [70.795557]  ? _raw_spin_unlock_irq+0x24/0x30
+  [70.795569]  btrfs_truncate_inode_items+0x339/0xe50
+  [70.795647]  btrfs_evict_inode+0x269/0x540
+  [70.795659]  ? dput.part.38+0x29/0x460
+  [70.795671]  evict+0xcd/0x190
+  [70.795682]  __dentry_kill+0xd6/0x180
+  [70.795754]  dput.part.38+0x2ad/0x460
+  [70.795765]  do_renameat2+0x3cb/0x540
+  [70.795777]  __x64_sys_rename+0x1c/0x20
+
+Reported-by: Dave Jones <davej@codemonkey.org.uk>
+Fixes: 28553fa992cb ("Btrfs: fix race between shrinking truncate and fiemap")
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+[ add note ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/inode.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4814,7 +4814,6 @@ search_again:
+               goto out;
+       }
+-      path->leave_spinning = 1;
+       ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+       if (ret < 0)
+               goto out;
+@@ -4966,7 +4965,6 @@ delete:
+                    root == fs_info->tree_root)) {
+                       struct btrfs_ref ref = { 0 };
+-                      btrfs_set_path_blocking(path);
+                       bytes_deleted += extent_num_bytes;
+                       btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF,
diff --git a/queue-5.5/btrfs-fix-race-between-shrinking-truncate-and-fiemap.patch b/queue-5.5/btrfs-fix-race-between-shrinking-truncate-and-fiemap.patch
new file mode 100644 (file)
index 0000000..d2d5df1
--- /dev/null
@@ -0,0 +1,112 @@
+From 28553fa992cb28be6a65566681aac6cafabb4f2d Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 7 Feb 2020 12:23:09 +0000
+Subject: Btrfs: fix race between shrinking truncate and fiemap
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 28553fa992cb28be6a65566681aac6cafabb4f2d upstream.
+
+When there is a fiemap executing in parallel with a shrinking truncate
+we can end up in a situation where we have extent maps for which we no
+longer have corresponding file extent items. This is generally harmless
+and at the moment the only consequences are missing file extent items
+representing holes after we expand the file size again after the
+truncate operation removed the prealloc extent items, and stale
+information for future fiemap calls (reporting extents that no longer
+exist or may have been reallocated to other files for example).
+
+Consider the following example:
+
+1) Our inode has a size of 128KiB, one 128KiB extent at file offset 0
+   and a 1MiB prealloc extent at file offset 128KiB;
+
+2) Task A starts doing a shrinking truncate of our inode to reduce it to
+   a size of 64KiB. Before it searches the subvolume tree for file
+   extent items to delete, it drops all the extent maps in the range
+   from 64KiB to (u64)-1 by calling btrfs_drop_extent_cache();
+
+3) Task B starts doing a fiemap against our inode. When looking up for
+   the inode's extent maps in the range from 128KiB to (u64)-1, it
+   doesn't find any in the inode's extent map tree, since they were
+   removed by task A.  Because it didn't find any in the extent map
+   tree, it scans the inode's subvolume tree for file extent items, and
+   it finds the 1MiB prealloc extent at file offset 128KiB, then it
+   creates an extent map based on that file extent item and adds it to
+   inode's extent map tree (this ends up being done by
+   btrfs_get_extent() <- btrfs_get_extent_fiemap() <-
+   get_extent_skip_holes());
+
+4) Task A then drops the prealloc extent at file offset 128KiB and
+   shrinks the 128KiB extent file offset 0 to a length of 64KiB. The
+   truncation operation finishes and we end up with an extent map
+   representing a 1MiB prealloc extent at file offset 128KiB, despite we
+   don't have any more that extent;
+
+After this the two types of problems we have are:
+
+1) Future calls to fiemap always report that a 1MiB prealloc extent
+   exists at file offset 128KiB. This is stale information, no longer
+   correct;
+
+2) If the size of the file is increased, by a truncate operation that
+   increases the file size or by a write into a file offset > 64KiB for
+   example, we end up not inserting file extent items to represent holes
+   for any range between 128KiB and 128KiB + 1MiB, since the hole
+   expansion function, btrfs_cont_expand() will skip hole insertion for
+   any range for which an extent map exists that represents a prealloc
+   extent. This causes fsck to complain about missing file extent items
+   when not using the NO_HOLES feature.
+
+The second issue could be often triggered by test case generic/561 from
+fstests, which runs fsstress and duperemove in parallel, and duperemove
+does frequent fiemap calls.
+
+Essentially the problems happens because fiemap does not acquire the
+inode's lock while truncate does, and fiemap locks the file range in the
+inode's iotree while truncate does not. So fix the issue by making
+btrfs_truncate_inode_items() lock the file range from the new file size
+to (u64)-1, so that it serializes with fiemap.
+
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/inode.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4757,6 +4757,8 @@ int btrfs_truncate_inode_items(struct bt
+       u64 bytes_deleted = 0;
+       bool be_nice = false;
+       bool should_throttle = false;
++      const u64 lock_start = ALIGN_DOWN(new_size, fs_info->sectorsize);
++      struct extent_state *cached_state = NULL;
+       BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
+@@ -4773,6 +4775,9 @@ int btrfs_truncate_inode_items(struct bt
+               return -ENOMEM;
+       path->reada = READA_BACK;
++      lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
++                       &cached_state);
++
+       /*
+        * We want to drop from the next block forward in case this new size is
+        * not block aligned since we will be keeping the last block of the
+@@ -5039,6 +5044,9 @@ out:
+               btrfs_ordered_update_i_size(inode, last_size, NULL);
+       }
++      unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
++                           &cached_state);
++
+       btrfs_free_path(path);
+       return ret;
+ }
diff --git a/queue-5.5/btrfs-handle-logged-extent-failure-properly.patch b/queue-5.5/btrfs-handle-logged-extent-failure-properly.patch
new file mode 100644 (file)
index 0000000..522d0c7
--- /dev/null
@@ -0,0 +1,43 @@
+From bd727173e4432fe6cb70ba108dc1f3602c5409d7 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 13 Feb 2020 10:47:30 -0500
+Subject: btrfs: handle logged extent failure properly
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit bd727173e4432fe6cb70ba108dc1f3602c5409d7 upstream.
+
+If we're allocating a logged extent we attempt to insert an extent
+record for the file extent directly.  We increase
+space_info->bytes_reserved, because the extent entry addition will call
+btrfs_update_block_group(), which will convert the ->bytes_reserved to
+->bytes_used.  However if we fail at any point while inserting the
+extent entry we will bail and leave space on ->bytes_reserved, which
+will trigger a WARN_ON() on umount.  Fix this by pinning the space if we
+fail to insert, which is what happens in every other failure case that
+involves adding the extent entry.
+
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/extent-tree.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -4430,6 +4430,8 @@ int btrfs_alloc_logged_file_extent(struc
+       ret = alloc_reserved_file_extent(trans, 0, root_objectid, 0, owner,
+                                        offset, ins, 1);
++      if (ret)
++              btrfs_pin_extent(fs_info, ins->objectid, ins->offset, 1);
+       btrfs_put_block_group(block_group);
+       return ret;
+ }
diff --git a/queue-5.5/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_messaging.patch b/queue-5.5/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_messaging.patch
new file mode 100644 (file)
index 0000000..7c83439
--- /dev/null
@@ -0,0 +1,34 @@
+From b4a81b87a4cfe2bb26a4a943b748d96a43ef20e8 Mon Sep 17 00:00:00 2001
+From: Wenwen Wang <wenwen@cs.uga.edu>
+Date: Tue, 20 Aug 2019 00:33:54 -0500
+Subject: ecryptfs: fix a memory leak bug in ecryptfs_init_messaging()
+
+From: Wenwen Wang <wenwen@cs.uga.edu>
+
+commit b4a81b87a4cfe2bb26a4a943b748d96a43ef20e8 upstream.
+
+In ecryptfs_init_messaging(), if the allocation for 'ecryptfs_msg_ctx_arr'
+fails, the previously allocated 'ecryptfs_daemon_hash' is not deallocated,
+leading to a memory leak bug. To fix this issue, free
+'ecryptfs_daemon_hash' before returning the error.
+
+Cc: stable@vger.kernel.org
+Fixes: 88b4a07e6610 ("[PATCH] eCryptfs: Public key transport mechanism")
+Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ecryptfs/messaging.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ecryptfs/messaging.c
++++ b/fs/ecryptfs/messaging.c
+@@ -379,6 +379,7 @@ int __init ecryptfs_init_messaging(void)
+                                       * ecryptfs_message_buf_len),
+                                      GFP_KERNEL);
+       if (!ecryptfs_msg_ctx_arr) {
++              kfree(ecryptfs_daemon_hash);
+               rc = -ENOMEM;
+               goto out;
+       }
diff --git a/queue-5.5/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch b/queue-5.5/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch
new file mode 100644 (file)
index 0000000..81591a9
--- /dev/null
@@ -0,0 +1,35 @@
+From fe2e082f5da5b4a0a92ae32978f81507ef37ec66 Mon Sep 17 00:00:00 2001
+From: Wenwen Wang <wenwen@cs.uga.edu>
+Date: Tue, 20 Aug 2019 00:16:40 -0500
+Subject: ecryptfs: fix a memory leak bug in parse_tag_1_packet()
+
+From: Wenwen Wang <wenwen@cs.uga.edu>
+
+commit fe2e082f5da5b4a0a92ae32978f81507ef37ec66 upstream.
+
+In parse_tag_1_packet(), if tag 1 packet contains a key larger than
+ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES, no cleanup is executed, leading to a
+memory leak on the allocated 'auth_tok_list_item'. To fix this issue, go to
+the label 'out_free' to perform the cleanup work.
+
+Cc: stable@vger.kernel.org
+Fixes: dddfa461fc89 ("[PATCH] eCryptfs: Public key; packet management")
+Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu>
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ecryptfs/keystore.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ecryptfs/keystore.c
++++ b/fs/ecryptfs/keystore.c
+@@ -1304,7 +1304,7 @@ parse_tag_1_packet(struct ecryptfs_crypt
+               printk(KERN_WARNING "Tag 1 packet contains key larger "
+                      "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
+               rc = -EINVAL;
+-              goto out;
++              goto out_free;
+       }
+       memcpy((*new_auth_tok)->session_key.encrypted_key,
+              &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));
diff --git a/queue-5.5/iommu-qcom-fix-bogus-detach-logic.patch b/queue-5.5/iommu-qcom-fix-bogus-detach-logic.patch
new file mode 100644 (file)
index 0000000..7de3de0
--- /dev/null
@@ -0,0 +1,83 @@
+From faf305c51aeabd1ea2d7131e798ef5f55f4a7750 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Tue, 18 Feb 2020 18:12:41 +0000
+Subject: iommu/qcom: Fix bogus detach logic
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+commit faf305c51aeabd1ea2d7131e798ef5f55f4a7750 upstream.
+
+Currently, the implementation of qcom_iommu_domain_free() is guaranteed
+to do one of two things: WARN() and leak everything, or dereference NULL
+and crash. That alone is terrible, but in fact the whole idea of trying
+to track the liveness of a domain via the qcom_domain->iommu pointer as
+a sanity check is full of fundamentally flawed assumptions. Make things
+robust and actually functional by not trying to be quite so clever.
+
+Reported-by: Brian Masney <masneyb@onstation.org>
+Tested-by: Brian Masney <masneyb@onstation.org>
+Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
+Fixes: 0ae349a0f33f ("iommu/qcom: Add qcom_iommu")
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Tested-by: Stephan Gerhold <stephan@gerhold.net>
+Cc: stable@vger.kernel.org # v4.14+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/qcom_iommu.c |   28 ++++++++++++----------------
+ 1 file changed, 12 insertions(+), 16 deletions(-)
+
+--- a/drivers/iommu/qcom_iommu.c
++++ b/drivers/iommu/qcom_iommu.c
+@@ -345,21 +345,19 @@ static void qcom_iommu_domain_free(struc
+ {
+       struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
+-      if (WARN_ON(qcom_domain->iommu))    /* forgot to detach? */
+-              return;
+-
+       iommu_put_dma_cookie(domain);
+-      /* NOTE: unmap can be called after client device is powered off,
+-       * for example, with GPUs or anything involving dma-buf.  So we
+-       * cannot rely on the device_link.  Make sure the IOMMU is on to
+-       * avoid unclocked accesses in the TLB inv path:
+-       */
+-      pm_runtime_get_sync(qcom_domain->iommu->dev);
+-
+-      free_io_pgtable_ops(qcom_domain->pgtbl_ops);
+-
+-      pm_runtime_put_sync(qcom_domain->iommu->dev);
++      if (qcom_domain->iommu) {
++              /*
++               * NOTE: unmap can be called after client device is powered
++               * off, for example, with GPUs or anything involving dma-buf.
++               * So we cannot rely on the device_link.  Make sure the IOMMU
++               * is on to avoid unclocked accesses in the TLB inv path:
++               */
++              pm_runtime_get_sync(qcom_domain->iommu->dev);
++              free_io_pgtable_ops(qcom_domain->pgtbl_ops);
++              pm_runtime_put_sync(qcom_domain->iommu->dev);
++      }
+       kfree(qcom_domain);
+ }
+@@ -405,7 +403,7 @@ static void qcom_iommu_detach_dev(struct
+       struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
+       unsigned i;
+-      if (!qcom_domain->iommu)
++      if (WARN_ON(!qcom_domain->iommu))
+               return;
+       pm_runtime_get_sync(qcom_iommu->dev);
+@@ -418,8 +416,6 @@ static void qcom_iommu_detach_dev(struct
+               ctx->domain = NULL;
+       }
+       pm_runtime_put_sync(qcom_iommu->dev);
+-
+-      qcom_domain->iommu = NULL;
+ }
+ static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
diff --git a/queue-5.5/iommu-vt-d-add-attach_deferred-helper.patch b/queue-5.5/iommu-vt-d-add-attach_deferred-helper.patch
new file mode 100644 (file)
index 0000000..49fbd02
--- /dev/null
@@ -0,0 +1,65 @@
+From 1d4615978f525b769990a4a4ef22fb1b9a04cdf1 Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Mon, 17 Feb 2020 17:12:37 +0100
+Subject: iommu/vt-d: Add attach_deferred() helper
+
+From: Joerg Roedel <jroedel@suse.de>
+
+commit 1d4615978f525b769990a4a4ef22fb1b9a04cdf1 upstream.
+
+Implement a helper function to check whether a device's attach process
+is deferred.
+
+Fixes: 1ee0186b9a12 ("iommu/vt-d: Refactor find_domain() helper")
+Cc: stable@vger.kernel.org # v5.5
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -732,6 +732,11 @@ static int iommu_dummy(struct device *de
+       return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
+ }
++static bool attach_deferred(struct device *dev)
++{
++      return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
++}
++
+ /**
+  * is_downstream_to_pci_bridge - test if a device belongs to the PCI
+  *                             sub-hierarchy of a candidate PCI-PCI bridge
+@@ -2424,8 +2429,7 @@ static struct dmar_domain *find_domain(s
+ {
+       struct device_domain_info *info;
+-      if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO ||
+-                   dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO))
++      if (unlikely(attach_deferred(dev) || iommu_dummy(dev)))
+               return NULL;
+       /* No lock here, assumes no domain exit in normal case */
+@@ -2438,7 +2442,7 @@ static struct dmar_domain *find_domain(s
+ static struct dmar_domain *deferred_attach_domain(struct device *dev)
+ {
+-      if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
++      if (unlikely(attach_deferred(dev))) {
+               struct iommu_domain *domain;
+               dev->archdata.iommu = NULL;
+@@ -5989,7 +5993,7 @@ intel_iommu_aux_get_pasid(struct iommu_d
+ static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
+                                          struct device *dev)
+ {
+-      return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
++      return attach_deferred(dev);
+ }
+ const struct iommu_ops intel_iommu_ops = {
diff --git a/queue-5.5/iommu-vt-d-do-deferred-attachment-in-iommu_need_mapping.patch b/queue-5.5/iommu-vt-d-do-deferred-attachment-in-iommu_need_mapping.patch
new file mode 100644 (file)
index 0000000..c0361b2
--- /dev/null
@@ -0,0 +1,71 @@
+From a11bfde9c77df1fd350ea27169ab921f511bf5d0 Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Mon, 17 Feb 2020 17:20:59 +0100
+Subject: iommu/vt-d: Do deferred attachment in iommu_need_mapping()
+
+From: Joerg Roedel <jroedel@suse.de>
+
+commit a11bfde9c77df1fd350ea27169ab921f511bf5d0 upstream.
+
+The attachment of deferred devices needs to happen before the check
+whether the device is identity mapped or not. Otherwise the check will
+return wrong results, cause warnings boot failures in kdump kernels, like
+
+       WARNING: CPU: 0 PID: 318 at ../drivers/iommu/intel-iommu.c:592 domain_get_iommu+0x61/0x70
+
+       [...]
+
+        Call Trace:
+         __intel_map_single+0x55/0x190
+         intel_alloc_coherent+0xac/0x110
+         dmam_alloc_attrs+0x50/0xa0
+         ahci_port_start+0xfb/0x1f0 [libahci]
+         ata_host_start.part.39+0x104/0x1e0 [libata]
+
+With the earlier check the kdump boot succeeds and a crashdump is written.
+
+Fixes: 1ee0186b9a12 ("iommu/vt-d: Refactor find_domain() helper")
+Cc: stable@vger.kernel.org # v5.5
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -2452,9 +2452,6 @@ static void do_deferred_attach(struct de
+ static struct dmar_domain *deferred_attach_domain(struct device *dev)
+ {
+-      if (unlikely(attach_deferred(dev)))
+-              do_deferred_attach(dev);
+-
+       return find_domain(dev);
+ }
+@@ -3478,6 +3475,9 @@ static bool iommu_need_mapping(struct de
+       if (iommu_dummy(dev))
+               return false;
++      if (unlikely(attach_deferred(dev)))
++              do_deferred_attach(dev);
++
+       ret = identity_mapping(dev);
+       if (ret) {
+               u64 dma_mask = *dev->dma_mask;
+@@ -3841,7 +3841,11 @@ bounce_map_single(struct device *dev, ph
+       int prot = 0;
+       int ret;
++      if (unlikely(attach_deferred(dev)))
++              do_deferred_attach(dev);
++
+       domain = deferred_attach_domain(dev);
++
+       if (WARN_ON(dir == DMA_NONE || !domain))
+               return DMA_MAPPING_ERROR;
diff --git a/queue-5.5/iommu-vt-d-move-deferred-device-attachment-into-helper-function.patch b/queue-5.5/iommu-vt-d-move-deferred-device-attachment-into-helper-function.patch
new file mode 100644 (file)
index 0000000..f9b4fe2
--- /dev/null
@@ -0,0 +1,54 @@
+From 034d98cc0cdcde2415c6f598fa9125e3eaa02569 Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Mon, 17 Feb 2020 17:16:19 +0100
+Subject: iommu/vt-d: Move deferred device attachment into helper function
+
+From: Joerg Roedel <jroedel@suse.de>
+
+commit 034d98cc0cdcde2415c6f598fa9125e3eaa02569 upstream.
+
+Move the code that does the deferred device attachment into a separate
+helper function.
+
+Fixes: 1ee0186b9a12 ("iommu/vt-d: Refactor find_domain() helper")
+Cc: stable@vger.kernel.org # v5.5
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |   20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -2440,16 +2440,20 @@ static struct dmar_domain *find_domain(s
+       return NULL;
+ }
+-static struct dmar_domain *deferred_attach_domain(struct device *dev)
++static void do_deferred_attach(struct device *dev)
+ {
+-      if (unlikely(attach_deferred(dev))) {
+-              struct iommu_domain *domain;
++      struct iommu_domain *domain;
++
++      dev->archdata.iommu = NULL;
++      domain = iommu_get_domain_for_dev(dev);
++      if (domain)
++              intel_iommu_attach_device(domain, dev);
++}
+-              dev->archdata.iommu = NULL;
+-              domain = iommu_get_domain_for_dev(dev);
+-              if (domain)
+-                      intel_iommu_attach_device(domain, dev);
+-      }
++static struct dmar_domain *deferred_attach_domain(struct device *dev)
++{
++      if (unlikely(attach_deferred(dev)))
++              do_deferred_attach(dev);
+       return find_domain(dev);
+ }
diff --git a/queue-5.5/iommu-vt-d-remove-deferred_attach_domain.patch b/queue-5.5/iommu-vt-d-remove-deferred_attach_domain.patch
new file mode 100644 (file)
index 0000000..1c085fe
--- /dev/null
@@ -0,0 +1,64 @@
+From 96d170f3b1a607612caf3618c534d5c64fc2d61b Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Mon, 17 Feb 2020 17:27:44 +0100
+Subject: iommu/vt-d: Remove deferred_attach_domain()
+
+From: Joerg Roedel <jroedel@suse.de>
+
+commit 96d170f3b1a607612caf3618c534d5c64fc2d61b upstream.
+
+The function is now only a wrapper around find_domain(). Remove the
+function and call find_domain() directly at the call-sites.
+
+Fixes: 1ee0186b9a12 ("iommu/vt-d: Refactor find_domain() helper")
+Cc: stable@vger.kernel.org # v5.5
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |   11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -2450,11 +2450,6 @@ static void do_deferred_attach(struct de
+               intel_iommu_attach_device(domain, dev);
+ }
+-static struct dmar_domain *deferred_attach_domain(struct device *dev)
+-{
+-      return find_domain(dev);
+-}
+-
+ static inline struct device_domain_info *
+ dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
+ {
+@@ -3526,7 +3521,7 @@ static dma_addr_t __intel_map_single(str
+       BUG_ON(dir == DMA_NONE);
+-      domain = deferred_attach_domain(dev);
++      domain = find_domain(dev);
+       if (!domain)
+               return DMA_MAPPING_ERROR;
+@@ -3746,7 +3741,7 @@ static int intel_map_sg(struct device *d
+       if (!iommu_need_mapping(dev))
+               return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
+-      domain = deferred_attach_domain(dev);
++      domain = find_domain(dev);
+       if (!domain)
+               return 0;
+@@ -3844,7 +3839,7 @@ bounce_map_single(struct device *dev, ph
+       if (unlikely(attach_deferred(dev)))
+               do_deferred_attach(dev);
+-      domain = deferred_attach_domain(dev);
++      domain = find_domain(dev);
+       if (WARN_ON(dir == DMA_NONE || !domain))
+               return DMA_MAPPING_ERROR;
diff --git a/queue-5.5/iommu-vt-d-simplify-check-in-identity_mapping.patch b/queue-5.5/iommu-vt-d-simplify-check-in-identity_mapping.patch
new file mode 100644 (file)
index 0000000..99052b2
--- /dev/null
@@ -0,0 +1,35 @@
+From 1ddb32da4a629fa7f87873d0b6836c2e1feb7518 Mon Sep 17 00:00:00 2001
+From: Joerg Roedel <jroedel@suse.de>
+Date: Mon, 17 Feb 2020 17:29:55 +0100
+Subject: iommu/vt-d: Simplify check in identity_mapping()
+
+From: Joerg Roedel <jroedel@suse.de>
+
+commit 1ddb32da4a629fa7f87873d0b6836c2e1feb7518 upstream.
+
+The function only has one call-site and there it is never called with
+dummy or deferred devices. Simplify the check in the function to
+account for that.
+
+Fixes: 1ee0186b9a12 ("iommu/vt-d: Refactor find_domain() helper")
+Cc: stable@vger.kernel.org # v5.5
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -2799,7 +2799,7 @@ static int identity_mapping(struct devic
+       struct device_domain_info *info;
+       info = dev->archdata.iommu;
+-      if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO)
++      if (info)
+               return (info->domain == si_domain);
+       return 0;
diff --git a/queue-5.5/series b/queue-5.5/series
new file mode 100644 (file)
index 0000000..e3659f5
--- /dev/null
@@ -0,0 +1,18 @@
+iommu-qcom-fix-bogus-detach-logic.patch
+iommu-vt-d-add-attach_deferred-helper.patch
+iommu-vt-d-move-deferred-device-attachment-into-helper-function.patch
+iommu-vt-d-do-deferred-attachment-in-iommu_need_mapping.patch
+iommu-vt-d-remove-deferred_attach_domain.patch
+iommu-vt-d-simplify-check-in-identity_mapping.patch
+alsa-hda-use-scnprintf-for-printing-texts-for-sysfs-procfs.patch
+alsa-hda-realtek-apply-quirk-for-msi-gp63-too.patch
+alsa-hda-realtek-apply-quirk-for-yet-another-msi-laptop.patch
+asoc-codec2codec-avoid-invalid-double-free-of-pcm-runtime.patch
+asoc-sun8i-codec-fix-setting-dai-data-format.patch
+tpm-revert-tpm_tis_spi_mod.ko-to-tpm_tis_spi.ko.patch
+tpm-initialize-crypto_id-of-allocated_banks-to-hash_algo__last.patch
+ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch
+ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_messaging.patch
+btrfs-fix-race-between-shrinking-truncate-and-fiemap.patch
+btrfs-don-t-set-path-leave_spinning-for-truncate.patch
+btrfs-handle-logged-extent-failure-properly.patch
diff --git a/queue-5.5/tpm-initialize-crypto_id-of-allocated_banks-to-hash_algo__last.patch b/queue-5.5/tpm-initialize-crypto_id-of-allocated_banks-to-hash_algo__last.patch
new file mode 100644 (file)
index 0000000..00f10bb
--- /dev/null
@@ -0,0 +1,45 @@
+From dc10e4181c05a2315ddc375e963b7c763b5ee0df Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Mon, 10 Feb 2020 11:00:41 +0100
+Subject: tpm: Initialize crypto_id of allocated_banks to HASH_ALGO__LAST
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+commit dc10e4181c05a2315ddc375e963b7c763b5ee0df upstream.
+
+chip->allocated_banks, an array of tpm_bank_info structures, contains the
+list of TPM algorithm IDs of allocated PCR banks. It also contains the
+corresponding ID of the crypto subsystem, so that users of the TPM driver
+can calculate a digest for a PCR extend operation.
+
+However, if there is no mapping between TPM algorithm ID and crypto ID, the
+crypto_id field of tpm_bank_info remains set to zero (the array is
+allocated and initialized with kcalloc() in tpm2_get_pcr_allocation()).
+Zero should not be used as value for unknown mappings, as it is a valid
+crypto ID (HASH_ALGO_MD4).
+
+Thus, initialize crypto_id to HASH_ALGO__LAST.
+
+Cc: stable@vger.kernel.org # 5.1.x
+Fixes: 879b589210a9 ("tpm: retrieve digest size of unknown algorithms with PCR read")
+Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
+Reviewed-by: Petr Vorel <pvorel@suse.cz>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm2-cmd.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/char/tpm/tpm2-cmd.c
++++ b/drivers/char/tpm/tpm2-cmd.c
+@@ -525,6 +525,8 @@ static int tpm2_init_bank_info(struct tp
+               return 0;
+       }
++      bank->crypto_id = HASH_ALGO__LAST;
++
+       return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size);
+ }
diff --git a/queue-5.5/tpm-revert-tpm_tis_spi_mod.ko-to-tpm_tis_spi.ko.patch b/queue-5.5/tpm-revert-tpm_tis_spi_mod.ko-to-tpm_tis_spi.ko.patch
new file mode 100644 (file)
index 0000000..5e84e8a
--- /dev/null
@@ -0,0 +1,649 @@
+From faaca0a0d48e7b122f6e7e2521f4f6fc487d0451 Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Date: Tue, 4 Feb 2020 14:16:27 +0200
+Subject: tpm: Revert tpm_tis_spi_mod.ko to tpm_tis_spi.ko.
+
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+
+commit faaca0a0d48e7b122f6e7e2521f4f6fc487d0451 upstream.
+
+Revert tpm_tis_spi_mod.ko back to tpm_tis_spi.ko as the rename could
+break user space scripts. This can be achieved by renaming tpm_tis_spi.c
+as tpm_tis_spi_main.c. Then tpm_tis_spi-y can be used inside the
+makefile.
+
+Cc: Andrey Pronin <apronin@chromium.org>
+Cc: Stephen Boyd <swboyd@chromium.org>
+Cc: stable@vger.kernel.org # 5.5.x
+Fixes: 797c0113c9a4 ("tpm: tpm_tis_spi: Support cr50 devices")
+Reported-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Tested-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Reviewed-by: Stephen Boyd <swboyd@chromium.org>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/Makefile           |    8 
+ drivers/char/tpm/tpm_tis_spi.c      |  298 ------------------------------------
+ drivers/char/tpm/tpm_tis_spi_main.c |  298 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 303 insertions(+), 301 deletions(-)
+
+--- a/drivers/char/tpm/Makefile
++++ b/drivers/char/tpm/Makefile
+@@ -21,9 +21,11 @@ tpm-$(CONFIG_EFI) += eventlog/efi.o
+ tpm-$(CONFIG_OF) += eventlog/of.o
+ obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
+ obj-$(CONFIG_TCG_TIS) += tpm_tis.o
+-obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi_mod.o
+-tpm_tis_spi_mod-y := tpm_tis_spi.o
+-tpm_tis_spi_mod-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o
++
++obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
++tpm_tis_spi-y := tpm_tis_spi_main.o
++tpm_tis_spi-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o
++
+ obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
+ obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
+ obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
+--- a/drivers/char/tpm/tpm_tis_spi.c
++++ /dev/null
+@@ -1,298 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- * Copyright (C) 2015 Infineon Technologies AG
+- * Copyright (C) 2016 STMicroelectronics SAS
+- *
+- * Authors:
+- * Peter Huewe <peter.huewe@infineon.com>
+- * Christophe Ricard <christophe-h.ricard@st.com>
+- *
+- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+- *
+- * Device driver for TCG/TCPA TPM (trusted platform module).
+- * Specifications at www.trustedcomputinggroup.org
+- *
+- * This device driver implements the TPM interface as defined in
+- * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native
+- * SPI access_.
+- *
+- * It is based on the original tpm_tis device driver from Leendert van
+- * Dorn and Kyleen Hall and Jarko Sakkinnen.
+- */
+-
+-#include <linux/acpi.h>
+-#include <linux/completion.h>
+-#include <linux/init.h>
+-#include <linux/interrupt.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/slab.h>
+-
+-#include <linux/of_device.h>
+-#include <linux/spi/spi.h>
+-#include <linux/tpm.h>
+-
+-#include "tpm.h"
+-#include "tpm_tis_core.h"
+-#include "tpm_tis_spi.h"
+-
+-#define MAX_SPI_FRAMESIZE 64
+-
+-/*
+- * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short,
+- * keep trying to read from the device until MISO goes high indicating the
+- * wait state has ended.
+- *
+- * [1] https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
+- */
+-static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy,
+-                                  struct spi_transfer *spi_xfer)
+-{
+-      struct spi_message m;
+-      int ret, i;
+-
+-      if ((phy->iobuf[3] & 0x01) == 0) {
+-              // handle SPI wait states
+-              phy->iobuf[0] = 0;
+-
+-              for (i = 0; i < TPM_RETRY; i++) {
+-                      spi_xfer->len = 1;
+-                      spi_message_init(&m);
+-                      spi_message_add_tail(spi_xfer, &m);
+-                      ret = spi_sync_locked(phy->spi_device, &m);
+-                      if (ret < 0)
+-                              return ret;
+-                      if (phy->iobuf[0] & 0x01)
+-                              break;
+-              }
+-
+-              if (i == TPM_RETRY)
+-                      return -ETIMEDOUT;
+-      }
+-
+-      return 0;
+-}
+-
+-int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
+-                       u8 *in, const u8 *out)
+-{
+-      struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
+-      int ret = 0;
+-      struct spi_message m;
+-      struct spi_transfer spi_xfer;
+-      u8 transfer_len;
+-
+-      spi_bus_lock(phy->spi_device->master);
+-
+-      while (len) {
+-              transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+-
+-              phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+-              phy->iobuf[1] = 0xd4;
+-              phy->iobuf[2] = addr >> 8;
+-              phy->iobuf[3] = addr;
+-
+-              memset(&spi_xfer, 0, sizeof(spi_xfer));
+-              spi_xfer.tx_buf = phy->iobuf;
+-              spi_xfer.rx_buf = phy->iobuf;
+-              spi_xfer.len = 4;
+-              spi_xfer.cs_change = 1;
+-
+-              spi_message_init(&m);
+-              spi_message_add_tail(&spi_xfer, &m);
+-              ret = spi_sync_locked(phy->spi_device, &m);
+-              if (ret < 0)
+-                      goto exit;
+-
+-              ret = phy->flow_control(phy, &spi_xfer);
+-              if (ret < 0)
+-                      goto exit;
+-
+-              spi_xfer.cs_change = 0;
+-              spi_xfer.len = transfer_len;
+-              spi_xfer.delay_usecs = 5;
+-
+-              if (in) {
+-                      spi_xfer.tx_buf = NULL;
+-              } else if (out) {
+-                      spi_xfer.rx_buf = NULL;
+-                      memcpy(phy->iobuf, out, transfer_len);
+-                      out += transfer_len;
+-              }
+-
+-              spi_message_init(&m);
+-              spi_message_add_tail(&spi_xfer, &m);
+-              reinit_completion(&phy->ready);
+-              ret = spi_sync_locked(phy->spi_device, &m);
+-              if (ret < 0)
+-                      goto exit;
+-
+-              if (in) {
+-                      memcpy(in, phy->iobuf, transfer_len);
+-                      in += transfer_len;
+-              }
+-
+-              len -= transfer_len;
+-      }
+-
+-exit:
+-      spi_bus_unlock(phy->spi_device->master);
+-      return ret;
+-}
+-
+-static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
+-                                u16 len, u8 *result)
+-{
+-      return tpm_tis_spi_transfer(data, addr, len, result, NULL);
+-}
+-
+-static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
+-                                 u16 len, const u8 *value)
+-{
+-      return tpm_tis_spi_transfer(data, addr, len, NULL, value);
+-}
+-
+-int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
+-{
+-      __le16 result_le;
+-      int rc;
+-
+-      rc = data->phy_ops->read_bytes(data, addr, sizeof(u16),
+-                                     (u8 *)&result_le);
+-      if (!rc)
+-              *result = le16_to_cpu(result_le);
+-
+-      return rc;
+-}
+-
+-int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
+-{
+-      __le32 result_le;
+-      int rc;
+-
+-      rc = data->phy_ops->read_bytes(data, addr, sizeof(u32),
+-                                     (u8 *)&result_le);
+-      if (!rc)
+-              *result = le32_to_cpu(result_le);
+-
+-      return rc;
+-}
+-
+-int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
+-{
+-      __le32 value_le;
+-      int rc;
+-
+-      value_le = cpu_to_le32(value);
+-      rc = data->phy_ops->write_bytes(data, addr, sizeof(u32),
+-                                      (u8 *)&value_le);
+-
+-      return rc;
+-}
+-
+-int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy,
+-                   int irq, const struct tpm_tis_phy_ops *phy_ops)
+-{
+-      phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+-      if (!phy->iobuf)
+-              return -ENOMEM;
+-
+-      phy->spi_device = spi;
+-
+-      return tpm_tis_core_init(&spi->dev, &phy->priv, irq, phy_ops, NULL);
+-}
+-
+-static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
+-      .read_bytes = tpm_tis_spi_read_bytes,
+-      .write_bytes = tpm_tis_spi_write_bytes,
+-      .read16 = tpm_tis_spi_read16,
+-      .read32 = tpm_tis_spi_read32,
+-      .write32 = tpm_tis_spi_write32,
+-};
+-
+-static int tpm_tis_spi_probe(struct spi_device *dev)
+-{
+-      struct tpm_tis_spi_phy *phy;
+-      int irq;
+-
+-      phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy),
+-                         GFP_KERNEL);
+-      if (!phy)
+-              return -ENOMEM;
+-
+-      phy->flow_control = tpm_tis_spi_flow_control;
+-
+-      /* If the SPI device has an IRQ then use that */
+-      if (dev->irq > 0)
+-              irq = dev->irq;
+-      else
+-              irq = -1;
+-
+-      init_completion(&phy->ready);
+-      return tpm_tis_spi_init(dev, phy, irq, &tpm_spi_phy_ops);
+-}
+-
+-typedef int (*tpm_tis_spi_probe_func)(struct spi_device *);
+-
+-static int tpm_tis_spi_driver_probe(struct spi_device *spi)
+-{
+-      const struct spi_device_id *spi_dev_id = spi_get_device_id(spi);
+-      tpm_tis_spi_probe_func probe_func;
+-
+-      probe_func = of_device_get_match_data(&spi->dev);
+-      if (!probe_func && spi_dev_id)
+-              probe_func = (tpm_tis_spi_probe_func)spi_dev_id->driver_data;
+-      if (!probe_func)
+-              return -ENODEV;
+-
+-      return probe_func(spi);
+-}
+-
+-static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume);
+-
+-static int tpm_tis_spi_remove(struct spi_device *dev)
+-{
+-      struct tpm_chip *chip = spi_get_drvdata(dev);
+-
+-      tpm_chip_unregister(chip);
+-      tpm_tis_remove(chip);
+-      return 0;
+-}
+-
+-static const struct spi_device_id tpm_tis_spi_id[] = {
+-      { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
+-      { "cr50", (unsigned long)cr50_spi_probe },
+-      {}
+-};
+-MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
+-
+-static const struct of_device_id of_tis_spi_match[] = {
+-      { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe },
+-      { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe },
+-      { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe },
+-      { .compatible = "google,cr50", .data = cr50_spi_probe },
+-      {}
+-};
+-MODULE_DEVICE_TABLE(of, of_tis_spi_match);
+-
+-static const struct acpi_device_id acpi_tis_spi_match[] = {
+-      {"SMO0768", 0},
+-      {}
+-};
+-MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match);
+-
+-static struct spi_driver tpm_tis_spi_driver = {
+-      .driver = {
+-              .name = "tpm_tis_spi",
+-              .pm = &tpm_tis_pm,
+-              .of_match_table = of_match_ptr(of_tis_spi_match),
+-              .acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
+-      },
+-      .probe = tpm_tis_spi_driver_probe,
+-      .remove = tpm_tis_spi_remove,
+-      .id_table = tpm_tis_spi_id,
+-};
+-module_spi_driver(tpm_tis_spi_driver);
+-
+-MODULE_DESCRIPTION("TPM Driver for native SPI access");
+-MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/char/tpm/tpm_tis_spi_main.c
+@@ -0,0 +1,298 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2015 Infineon Technologies AG
++ * Copyright (C) 2016 STMicroelectronics SAS
++ *
++ * Authors:
++ * Peter Huewe <peter.huewe@infineon.com>
++ * Christophe Ricard <christophe-h.ricard@st.com>
++ *
++ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
++ *
++ * Device driver for TCG/TCPA TPM (trusted platform module).
++ * Specifications at www.trustedcomputinggroup.org
++ *
++ * This device driver implements the TPM interface as defined in
++ * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native
++ * SPI access_.
++ *
++ * It is based on the original tpm_tis device driver from Leendert van
++ * Dorn and Kyleen Hall and Jarko Sakkinnen.
++ */
++
++#include <linux/acpi.h>
++#include <linux/completion.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#include <linux/of_device.h>
++#include <linux/spi/spi.h>
++#include <linux/tpm.h>
++
++#include "tpm.h"
++#include "tpm_tis_core.h"
++#include "tpm_tis_spi.h"
++
++#define MAX_SPI_FRAMESIZE 64
++
++/*
++ * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short,
++ * keep trying to read from the device until MISO goes high indicating the
++ * wait state has ended.
++ *
++ * [1] https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
++ */
++static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy,
++                                  struct spi_transfer *spi_xfer)
++{
++      struct spi_message m;
++      int ret, i;
++
++      if ((phy->iobuf[3] & 0x01) == 0) {
++              // handle SPI wait states
++              phy->iobuf[0] = 0;
++
++              for (i = 0; i < TPM_RETRY; i++) {
++                      spi_xfer->len = 1;
++                      spi_message_init(&m);
++                      spi_message_add_tail(spi_xfer, &m);
++                      ret = spi_sync_locked(phy->spi_device, &m);
++                      if (ret < 0)
++                              return ret;
++                      if (phy->iobuf[0] & 0x01)
++                              break;
++              }
++
++              if (i == TPM_RETRY)
++                      return -ETIMEDOUT;
++      }
++
++      return 0;
++}
++
++int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
++                       u8 *in, const u8 *out)
++{
++      struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
++      int ret = 0;
++      struct spi_message m;
++      struct spi_transfer spi_xfer;
++      u8 transfer_len;
++
++      spi_bus_lock(phy->spi_device->master);
++
++      while (len) {
++              transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
++
++              phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
++              phy->iobuf[1] = 0xd4;
++              phy->iobuf[2] = addr >> 8;
++              phy->iobuf[3] = addr;
++
++              memset(&spi_xfer, 0, sizeof(spi_xfer));
++              spi_xfer.tx_buf = phy->iobuf;
++              spi_xfer.rx_buf = phy->iobuf;
++              spi_xfer.len = 4;
++              spi_xfer.cs_change = 1;
++
++              spi_message_init(&m);
++              spi_message_add_tail(&spi_xfer, &m);
++              ret = spi_sync_locked(phy->spi_device, &m);
++              if (ret < 0)
++                      goto exit;
++
++              ret = phy->flow_control(phy, &spi_xfer);
++              if (ret < 0)
++                      goto exit;
++
++              spi_xfer.cs_change = 0;
++              spi_xfer.len = transfer_len;
++              spi_xfer.delay_usecs = 5;
++
++              if (in) {
++                      spi_xfer.tx_buf = NULL;
++              } else if (out) {
++                      spi_xfer.rx_buf = NULL;
++                      memcpy(phy->iobuf, out, transfer_len);
++                      out += transfer_len;
++              }
++
++              spi_message_init(&m);
++              spi_message_add_tail(&spi_xfer, &m);
++              reinit_completion(&phy->ready);
++              ret = spi_sync_locked(phy->spi_device, &m);
++              if (ret < 0)
++                      goto exit;
++
++              if (in) {
++                      memcpy(in, phy->iobuf, transfer_len);
++                      in += transfer_len;
++              }
++
++              len -= transfer_len;
++      }
++
++exit:
++      spi_bus_unlock(phy->spi_device->master);
++      return ret;
++}
++
++static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
++                                u16 len, u8 *result)
++{
++      return tpm_tis_spi_transfer(data, addr, len, result, NULL);
++}
++
++static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
++                                 u16 len, const u8 *value)
++{
++      return tpm_tis_spi_transfer(data, addr, len, NULL, value);
++}
++
++int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
++{
++      __le16 result_le;
++      int rc;
++
++      rc = data->phy_ops->read_bytes(data, addr, sizeof(u16),
++                                     (u8 *)&result_le);
++      if (!rc)
++              *result = le16_to_cpu(result_le);
++
++      return rc;
++}
++
++int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
++{
++      __le32 result_le;
++      int rc;
++
++      rc = data->phy_ops->read_bytes(data, addr, sizeof(u32),
++                                     (u8 *)&result_le);
++      if (!rc)
++              *result = le32_to_cpu(result_le);
++
++      return rc;
++}
++
++int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
++{
++      __le32 value_le;
++      int rc;
++
++      value_le = cpu_to_le32(value);
++      rc = data->phy_ops->write_bytes(data, addr, sizeof(u32),
++                                      (u8 *)&value_le);
++
++      return rc;
++}
++
++int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy,
++                   int irq, const struct tpm_tis_phy_ops *phy_ops)
++{
++      phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
++      if (!phy->iobuf)
++              return -ENOMEM;
++
++      phy->spi_device = spi;
++
++      return tpm_tis_core_init(&spi->dev, &phy->priv, irq, phy_ops, NULL);
++}
++
++static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
++      .read_bytes = tpm_tis_spi_read_bytes,
++      .write_bytes = tpm_tis_spi_write_bytes,
++      .read16 = tpm_tis_spi_read16,
++      .read32 = tpm_tis_spi_read32,
++      .write32 = tpm_tis_spi_write32,
++};
++
++static int tpm_tis_spi_probe(struct spi_device *dev)
++{
++      struct tpm_tis_spi_phy *phy;
++      int irq;
++
++      phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy),
++                         GFP_KERNEL);
++      if (!phy)
++              return -ENOMEM;
++
++      phy->flow_control = tpm_tis_spi_flow_control;
++
++      /* If the SPI device has an IRQ then use that */
++      if (dev->irq > 0)
++              irq = dev->irq;
++      else
++              irq = -1;
++
++      init_completion(&phy->ready);
++      return tpm_tis_spi_init(dev, phy, irq, &tpm_spi_phy_ops);
++}
++
++typedef int (*tpm_tis_spi_probe_func)(struct spi_device *);
++
++static int tpm_tis_spi_driver_probe(struct spi_device *spi)
++{
++      const struct spi_device_id *spi_dev_id = spi_get_device_id(spi);
++      tpm_tis_spi_probe_func probe_func;
++
++      probe_func = of_device_get_match_data(&spi->dev);
++      if (!probe_func && spi_dev_id)
++              probe_func = (tpm_tis_spi_probe_func)spi_dev_id->driver_data;
++      if (!probe_func)
++              return -ENODEV;
++
++      return probe_func(spi);
++}
++
++static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume);
++
++static int tpm_tis_spi_remove(struct spi_device *dev)
++{
++      struct tpm_chip *chip = spi_get_drvdata(dev);
++
++      tpm_chip_unregister(chip);
++      tpm_tis_remove(chip);
++      return 0;
++}
++
++static const struct spi_device_id tpm_tis_spi_id[] = {
++      { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
++      { "cr50", (unsigned long)cr50_spi_probe },
++      {}
++};
++MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
++
++static const struct of_device_id of_tis_spi_match[] = {
++      { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe },
++      { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe },
++      { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe },
++      { .compatible = "google,cr50", .data = cr50_spi_probe },
++      {}
++};
++MODULE_DEVICE_TABLE(of, of_tis_spi_match);
++
++static const struct acpi_device_id acpi_tis_spi_match[] = {
++      {"SMO0768", 0},
++      {}
++};
++MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match);
++
++static struct spi_driver tpm_tis_spi_driver = {
++      .driver = {
++              .name = "tpm_tis_spi",
++              .pm = &tpm_tis_pm,
++              .of_match_table = of_match_ptr(of_tis_spi_match),
++              .acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
++      },
++      .probe = tpm_tis_spi_driver_probe,
++      .remove = tpm_tis_spi_remove,
++      .id_table = tpm_tis_spi_id,
++};
++module_spi_driver(tpm_tis_spi_driver);
++
++MODULE_DESCRIPTION("TPM Driver for native SPI access");
++MODULE_LICENSE("GPL");