--- /dev/null
+From 67e40054de86aae520ddc2a072d7f6951812a14f Mon Sep 17 00:00:00 2001
+From: Qinglang Miao <miaoqinglang@huawei.com>
+Date: Fri, 15 Jan 2021 10:22:50 +0800
+Subject: ACPI: configfs: add missing check after configfs_register_default_group()
+
+From: Qinglang Miao <miaoqinglang@huawei.com>
+
+commit 67e40054de86aae520ddc2a072d7f6951812a14f upstream.
+
+A list_add corruption is reported by Hulk Robot like this:
+==============
+list_add corruption.
+Call Trace:
+link_obj+0xc0/0x1c0
+link_group+0x21/0x140
+configfs_register_subsystem+0xdb/0x380
+acpi_configfs_init+0x25/0x1000 [acpi_configfs]
+do_one_initcall+0x149/0x820
+do_init_module+0x1ef/0x720
+load_module+0x35c8/0x4380
+__do_sys_finit_module+0x10d/0x1a0
+do_syscall_64+0x34/0x80
+
+It's because of the missing check after configfs_register_default_group,
+where configfs_unregister_subsystem should be called once failure.
+
+Fixes: 612bd01fc6e0 ("ACPI: add support for loading SSDTs via configfs")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Suggested-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
+Cc: 4.10+ <stable@vger.kernel.org> # 4.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/acpi_configfs.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/acpi/acpi_configfs.c
++++ b/drivers/acpi/acpi_configfs.c
+@@ -267,7 +267,12 @@ static int __init acpi_configfs_init(voi
+
+ acpi_table_group = configfs_register_default_group(root, "table",
+ &acpi_tables_type);
+- return PTR_ERR_OR_ZERO(acpi_table_group);
++ if (IS_ERR(acpi_table_group)) {
++ configfs_unregister_subsystem(&acpi_configfs);
++ return PTR_ERR(acpi_table_group);
++ }
++
++ return 0;
+ }
+ module_init(acpi_configfs_init);
+
--- /dev/null
+From e1e6bd2995ac0e1ad0c2a2d906a06f59ce2ed293 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 11 Feb 2021 19:30:01 +0100
+Subject: ACPI: property: Fix fwnode string properties matching
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit e1e6bd2995ac0e1ad0c2a2d906a06f59ce2ed293 upstream.
+
+Property matching does not work for ACPI fwnodes if the value of the
+given property is not represented as a package in the _DSD package
+containing it. For example, the "compatible" property in the _DSD
+below
+
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () {"compatible", "ethernet-phy-ieee802.3-c45"}
+ }
+ })
+
+will not be found by fwnode_property_match_string(), because the ACPI
+code handling device properties does not regard the single value as a
+"list" in that case.
+
+Namely, fwnode_property_match_string() invoked to match a given
+string property value first calls fwnode_property_read_string_array()
+with the last two arguments equal to NULL and 0, respectively, in
+order to count the items in the value of the given property, with the
+assumption that this value may be an array. For ACPI fwnodes, that
+operation is carried out by acpi_node_prop_read() which calls
+acpi_data_prop_read() for this purpose. However, when the return
+(val) pointer is NULL, that function only looks for a property whose
+value is a package without checking the single-value case at all.
+
+To fix that, make acpi_data_prop_read() check the single-value
+case if its return pointer argument is NULL and modify
+acpi_data_prop_read_single() handling that case to attempt to
+read the value of the property if the return pointer is NULL
+and return 1 if that succeeds.
+
+Fixes: 3708184afc77 ("device property: Move FW type specific functionality to FW specific files")
+Reported-by: Calvin Johnson <calvin.johnson@oss.nxp.com>
+Cc: 4.13+ <stable@vger.kernel.org> # 4.13+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/acpi/property.c | 44 +++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 33 insertions(+), 11 deletions(-)
+
+--- a/drivers/acpi/property.c
++++ b/drivers/acpi/property.c
+@@ -794,9 +794,6 @@ static int acpi_data_prop_read_single(co
+ const union acpi_object *obj;
+ int ret;
+
+- if (!val)
+- return -EINVAL;
+-
+ if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
+ ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
+ if (ret)
+@@ -806,28 +803,43 @@ static int acpi_data_prop_read_single(co
+ case DEV_PROP_U8:
+ if (obj->integer.value > U8_MAX)
+ return -EOVERFLOW;
+- *(u8 *)val = obj->integer.value;
++
++ if (val)
++ *(u8 *)val = obj->integer.value;
++
+ break;
+ case DEV_PROP_U16:
+ if (obj->integer.value > U16_MAX)
+ return -EOVERFLOW;
+- *(u16 *)val = obj->integer.value;
++
++ if (val)
++ *(u16 *)val = obj->integer.value;
++
+ break;
+ case DEV_PROP_U32:
+ if (obj->integer.value > U32_MAX)
+ return -EOVERFLOW;
+- *(u32 *)val = obj->integer.value;
++
++ if (val)
++ *(u32 *)val = obj->integer.value;
++
+ break;
+ default:
+- *(u64 *)val = obj->integer.value;
++ if (val)
++ *(u64 *)val = obj->integer.value;
++
+ break;
+ }
++
++ if (!val)
++ return 1;
+ } else if (proptype == DEV_PROP_STRING) {
+ ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
+ if (ret)
+ return ret;
+
+- *(char **)val = obj->string.pointer;
++ if (val)
++ *(char **)val = obj->string.pointer;
+
+ return 1;
+ } else {
+@@ -841,7 +853,7 @@ int acpi_dev_prop_read_single(struct acp
+ {
+ int ret;
+
+- if (!adev)
++ if (!adev || !val)
+ return -EINVAL;
+
+ ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
+@@ -935,10 +947,20 @@ static int acpi_data_prop_read(const str
+ const union acpi_object *items;
+ int ret;
+
+- if (val && nval == 1) {
++ if (nval == 1 || !val) {
+ ret = acpi_data_prop_read_single(data, propname, proptype, val);
+- if (ret >= 0)
++ /*
++ * The overflow error means that the property is there and it is
++ * single-value, but its type does not match, so return.
++ */
++ if (ret >= 0 || ret == -EOVERFLOW)
+ return ret;
++
++ /*
++ * Reading this property as a single-value one failed, but its
++ * value may still be represented as one-element array, so
++ * continue.
++ */
+ }
+
+ ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
--- /dev/null
+From 0d3070f5e6551d8a759619e85736e49a3bf40398 Mon Sep 17 00:00:00 2001
+From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Date: Fri, 12 Feb 2021 17:10:22 +0200
+Subject: ALSA: hda: Add another CometLake-H PCI ID
+
+From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+
+commit 0d3070f5e6551d8a759619e85736e49a3bf40398 upstream.
+
+Add one more HD Audio PCI ID for CometLake-H PCH.
+
+Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210212151022.2568567-1-kai.vehmanen@linux.intel.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/hda_intel.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -2447,6 +2447,8 @@ static const struct pci_device_id azx_id
+ /* CometLake-H */
+ { PCI_DEVICE(0x8086, 0x06C8),
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
++ { PCI_DEVICE(0x8086, 0xf1c8),
++ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+ /* CometLake-S */
+ { PCI_DEVICE(0x8086, 0xa3f0),
+ .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
--- /dev/null
+From 4841b8e6318a7f0ae57c4e5ec09032ea057c97a8 Mon Sep 17 00:00:00 2001
+From: PeiSen Hou <pshou@realtek.com>
+Date: Tue, 2 Feb 2021 10:30:22 +0100
+Subject: ALSA: hda/realtek: modify EAPD in the ALC886
+
+From: PeiSen Hou <pshou@realtek.com>
+
+commit 4841b8e6318a7f0ae57c4e5ec09032ea057c97a8 upstream.
+
+Modify 0x20 index 7 bit 5 to 1, make the 0x15 EAPD the same as 0x14.
+
+Signed-off-by: PeiSen Hou <pshou@realtek.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/e62c5058957f48d8b8953e97135ff108@realtek.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_realtek.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -1895,6 +1895,7 @@ enum {
+ ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
+ ALC889_FIXUP_VAIO_TT,
+ ALC888_FIXUP_EEE1601,
++ ALC886_FIXUP_EAPD,
+ ALC882_FIXUP_EAPD,
+ ALC883_FIXUP_EAPD,
+ ALC883_FIXUP_ACER_EAPD,
+@@ -2228,6 +2229,15 @@ static const struct hda_fixup alc882_fix
+ { }
+ }
+ },
++ [ALC886_FIXUP_EAPD] = {
++ .type = HDA_FIXUP_VERBS,
++ .v.verbs = (const struct hda_verb[]) {
++ /* change to EAPD mode */
++ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
++ { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 },
++ { }
++ }
++ },
+ [ALC882_FIXUP_EAPD] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+@@ -2500,6 +2510,7 @@ static const struct snd_pci_quirk alc882
+ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
+
+ SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
++ SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_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(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
--- /dev/null
+From d797bd9897e3559eb48d68368550d637d32e468c Mon Sep 17 00:00:00 2001
+From: Kai Krakow <kai@kaishome.de>
+Date: Wed, 10 Feb 2021 13:07:26 +0800
+Subject: bcache: Give btree_io_wq correct semantics again
+
+From: Kai Krakow <kai@kaishome.de>
+
+commit d797bd9897e3559eb48d68368550d637d32e468c upstream.
+
+Before killing `btree_io_wq`, the queue was allocated using
+`create_singlethread_workqueue()` which has `WQ_MEM_RECLAIM`. After
+killing it, it no longer had this property but `system_wq` is not
+single threaded.
+
+Let's combine both worlds and make it multi threaded but able to
+reclaim memory.
+
+Cc: Coly Li <colyli@suse.de>
+Cc: stable@vger.kernel.org # 5.4+
+Signed-off-by: Kai Krakow <kai@kaishome.de>
+Signed-off-by: Coly Li <colyli@suse.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/bcache/btree.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/bcache/btree.c
++++ b/drivers/md/bcache/btree.c
+@@ -2670,7 +2670,7 @@ void bch_btree_exit(void)
+
+ int __init bch_btree_init(void)
+ {
+- btree_io_wq = create_singlethread_workqueue("bch_btree_io");
++ btree_io_wq = alloc_workqueue("bch_btree_io", WQ_MEM_RECLAIM, 0);
+ if (!btree_io_wq)
+ return -ENOMEM;
+
--- /dev/null
+From afe78ab46f638ecdf80a35b122ffc92c20d9ae5d Mon Sep 17 00:00:00 2001
+From: Kai Krakow <kai@kaishome.de>
+Date: Wed, 10 Feb 2021 13:07:27 +0800
+Subject: bcache: Move journal work to new flush wq
+
+From: Kai Krakow <kai@kaishome.de>
+
+commit afe78ab46f638ecdf80a35b122ffc92c20d9ae5d upstream.
+
+This is potentially long running and not latency sensitive, let's get
+it out of the way of other latency sensitive events.
+
+As observed in the previous commit, the `system_wq` comes easily
+congested by bcache, and this fixes a few more stalls I was observing
+every once in a while.
+
+Let's not make this `WQ_MEM_RECLAIM` as it showed to reduce performance
+of boot and file system operations in my tests. Also, without
+`WQ_MEM_RECLAIM`, I no longer see desktop stalls. This matches the
+previous behavior as `system_wq` also does no memory reclaim:
+
+> // workqueue.c:
+> system_wq = alloc_workqueue("events", 0, 0);
+
+Cc: Coly Li <colyli@suse.de>
+Cc: stable@vger.kernel.org # 5.4+
+Signed-off-by: Kai Krakow <kai@kaishome.de>
+Signed-off-by: Coly Li <colyli@suse.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/bcache/bcache.h | 1 +
+ drivers/md/bcache/journal.c | 4 ++--
+ drivers/md/bcache/super.c | 16 ++++++++++++++++
+ 3 files changed, 19 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/bcache/bcache.h
++++ b/drivers/md/bcache/bcache.h
+@@ -986,6 +986,7 @@ void bch_write_bdev_super(struct cached_
+
+ extern struct workqueue_struct *bcache_wq;
+ extern struct workqueue_struct *bch_journal_wq;
++extern struct workqueue_struct *bch_flush_wq;
+ extern struct mutex bch_register_lock;
+ extern struct list_head bch_cache_sets;
+
+--- a/drivers/md/bcache/journal.c
++++ b/drivers/md/bcache/journal.c
+@@ -958,8 +958,8 @@ atomic_t *bch_journal(struct cache_set *
+ journal_try_write(c);
+ } else if (!w->dirty) {
+ w->dirty = true;
+- schedule_delayed_work(&c->journal.work,
+- msecs_to_jiffies(c->journal_delay_ms));
++ queue_delayed_work(bch_flush_wq, &c->journal.work,
++ msecs_to_jiffies(c->journal_delay_ms));
+ spin_unlock(&c->journal.lock);
+ } else {
+ spin_unlock(&c->journal.lock);
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -48,6 +48,7 @@ static int bcache_major;
+ static DEFINE_IDA(bcache_device_idx);
+ static wait_queue_head_t unregister_wait;
+ struct workqueue_struct *bcache_wq;
++struct workqueue_struct *bch_flush_wq;
+ struct workqueue_struct *bch_journal_wq;
+
+
+@@ -2652,6 +2653,8 @@ static void bcache_exit(void)
+ destroy_workqueue(bcache_wq);
+ if (bch_journal_wq)
+ destroy_workqueue(bch_journal_wq);
++ if (bch_flush_wq)
++ destroy_workqueue(bch_flush_wq);
+ bch_btree_exit();
+
+ if (bcache_major)
+@@ -2715,6 +2718,19 @@ static int __init bcache_init(void)
+ if (!bcache_wq)
+ goto err;
+
++ /*
++ * Let's not make this `WQ_MEM_RECLAIM` for the following reasons:
++ *
++ * 1. It used `system_wq` before which also does no memory reclaim.
++ * 2. With `WQ_MEM_RECLAIM` desktop stalls, increased boot times, and
++ * reduced throughput can be observed.
++ *
++ * We still want to user our own queue to not congest the `system_wq`.
++ */
++ bch_flush_wq = alloc_workqueue("bch_flush", 0, 0);
++ if (!bch_flush_wq)
++ goto err;
++
+ bch_journal_wq = alloc_workqueue("bch_journal", WQ_MEM_RECLAIM, 0);
+ if (!bch_journal_wq)
+ goto err;
--- /dev/null
+From 97f433c3601a24d3513d06f575a389a2ca4e11e4 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 23 Feb 2021 19:25:30 -0700
+Subject: blk-settings: align max_sectors on "logical_block_size" boundary
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 97f433c3601a24d3513d06f575a389a2ca4e11e4 upstream.
+
+We get I/O errors when we run md-raid1 on the top of dm-integrity on the
+top of ramdisk.
+device-mapper: integrity: Bio not aligned on 8 sectors: 0xff00, 0xff
+device-mapper: integrity: Bio not aligned on 8 sectors: 0xff00, 0xff
+device-mapper: integrity: Bio not aligned on 8 sectors: 0xffff, 0x1
+device-mapper: integrity: Bio not aligned on 8 sectors: 0xffff, 0x1
+device-mapper: integrity: Bio not aligned on 8 sectors: 0x8048, 0xff
+device-mapper: integrity: Bio not aligned on 8 sectors: 0x8147, 0xff
+device-mapper: integrity: Bio not aligned on 8 sectors: 0x8246, 0xff
+device-mapper: integrity: Bio not aligned on 8 sectors: 0x8345, 0xbb
+
+The ramdisk device has logical_block_size 512 and max_sectors 255. The
+dm-integrity device uses logical_block_size 4096 and it doesn't affect the
+"max_sectors" value - thus, it inherits 255 from the ramdisk. So, we have
+a device with max_sectors not aligned on logical_block_size.
+
+The md-raid device sees that the underlying leg has max_sectors 255 and it
+will split the bios on 255-sector boundary, making the bios unaligned on
+logical_block_size.
+
+In order to fix the bug, we round down max_sectors to logical_block_size.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-settings.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -473,6 +473,14 @@ void blk_queue_stack_limits(struct reque
+ }
+ EXPORT_SYMBOL(blk_queue_stack_limits);
+
++static unsigned int blk_round_down_sectors(unsigned int sectors, unsigned int lbs)
++{
++ sectors = round_down(sectors, lbs >> SECTOR_SHIFT);
++ if (sectors < PAGE_SIZE >> SECTOR_SHIFT)
++ sectors = PAGE_SIZE >> SECTOR_SHIFT;
++ return sectors;
++}
++
+ /**
+ * blk_stack_limits - adjust queue_limits for stacked devices
+ * @t: the stacking driver limits (top device)
+@@ -586,6 +594,10 @@ int blk_stack_limits(struct queue_limits
+ ret = -1;
+ }
+
++ t->max_sectors = blk_round_down_sectors(t->max_sectors, t->logical_block_size);
++ t->max_hw_sectors = blk_round_down_sectors(t->max_hw_sectors, t->logical_block_size);
++ t->max_dev_sectors = blk_round_down_sectors(t->max_dev_sectors, t->logical_block_size);
++
+ /* Discard alignment and granularity */
+ if (b->discard_granularity) {
+ alignment = queue_limit_discard_alignment(b, start);
--- /dev/null
+From 867ed321f90d06aaba84e2c91de51cd3038825ef Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 14 Jan 2021 14:02:46 -0500
+Subject: btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 867ed321f90d06aaba84e2c91de51cd3038825ef upstream.
+
+While testing my error handling patches, I added a error injection site
+at btrfs_inc_extent_ref, to validate the error handling I added was
+doing the correct thing. However I hit a pretty ugly corruption while
+doing this check, with the following error injection stack trace:
+
+btrfs_inc_extent_ref
+ btrfs_copy_root
+ create_reloc_root
+ btrfs_init_reloc_root
+ btrfs_record_root_in_trans
+ btrfs_start_transaction
+ btrfs_update_inode
+ btrfs_update_time
+ touch_atime
+ file_accessed
+ btrfs_file_mmap
+
+This is because we do not catch the error from btrfs_inc_extent_ref,
+which in practice would be ENOMEM, which means we lose the extent
+references for a root that has already been allocated and inserted,
+which is the problem. Fix this by aborting the transaction if we fail
+to do the reference modification.
+
+CC: stable@vger.kernel.org # 4.4+
+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/ctree.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -260,9 +260,10 @@ int btrfs_copy_root(struct btrfs_trans_h
+ ret = btrfs_inc_ref(trans, root, cow, 1);
+ else
+ ret = btrfs_inc_ref(trans, root, cow, 0);
+-
+- if (ret)
++ if (ret) {
++ btrfs_abort_transaction(trans, ret);
+ return ret;
++ }
+
+ btrfs_mark_buffer_dirty(cow);
+ *cow_ret = cow;
--- /dev/null
+From 72c9925f87c8b74f36f8e75a4cd93d964538d3ca Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Thu, 4 Feb 2021 14:35:44 +0000
+Subject: btrfs: fix extent buffer leak on failure to copy root
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 72c9925f87c8b74f36f8e75a4cd93d964538d3ca upstream.
+
+At btrfs_copy_root(), if the call to btrfs_inc_ref() fails we end up
+returning without unlocking and releasing our reference on the extent
+buffer named "cow" we previously allocated with btrfs_alloc_tree_block().
+
+So fix that by unlocking the extent buffer and dropping our reference on
+it before returning.
+
+Fixes: be20aa9dbadc8c ("Btrfs: Add mount option to turn off data cow")
+CC: stable@vger.kernel.org # 4.4+
+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/ctree.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -261,6 +261,8 @@ int btrfs_copy_root(struct btrfs_trans_h
+ else
+ ret = btrfs_inc_ref(trans, root, cow, 0);
+ if (ret) {
++ btrfs_tree_unlock(cow);
++ free_extent_buffer(cow);
+ btrfs_abort_transaction(trans, ret);
+ return ret;
+ }
--- /dev/null
+From c78a10aebb275c38d0cfccae129a803fe622e305 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 14 Jan 2021 14:02:42 -0500
+Subject: btrfs: fix reloc root leak with 0 ref reloc roots on recovery
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit c78a10aebb275c38d0cfccae129a803fe622e305 upstream.
+
+When recovering a relocation, if we run into a reloc root that has 0
+refs we simply add it to the reloc_control->reloc_roots list, and then
+clean it up later. The problem with this is __del_reloc_root() doesn't
+do anything if the root isn't in the radix tree, which in this case it
+won't be because we never call __add_reloc_root() on the reloc_root.
+
+This exit condition simply isn't correct really. During normal
+operation we can remove ourselves from the rb tree and then we're meant
+to clean up later at merge_reloc_roots() time, and this happens
+correctly. During recovery we're depending on free_reloc_roots() to
+drop our references, but we're short-circuiting.
+
+Fix this by continuing to check if we're on the list and dropping
+ourselves from the reloc_control root list and dropping our reference
+appropriately. Change the corresponding BUG_ON() to an ASSERT() that
+does the correct thing if we aren't in the rb tree.
+
+CC: stable@vger.kernel.org # 4.4+
+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/relocation.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -1336,9 +1336,7 @@ static void __del_reloc_root(struct btrf
+ RB_CLEAR_NODE(&node->rb_node);
+ }
+ spin_unlock(&rc->reloc_root_tree.lock);
+- if (!node)
+- return;
+- BUG_ON((struct btrfs_root *)node->data != root);
++ ASSERT(!node || (struct btrfs_root *)node->data == root);
+ }
+
+ spin_lock(&fs_info->trans_lock);
--- /dev/null
+From 938fcbfb0cbcf532a1869efab58e6009446b1ced Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 14 Jan 2021 14:02:43 -0500
+Subject: btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 938fcbfb0cbcf532a1869efab58e6009446b1ced upstream.
+
+While doing error injection testing with my relocation patches I hit the
+following assert:
+
+ assertion failed: list_empty(&block_group->dirty_list), in fs/btrfs/block-group.c:3356
+ ------------[ cut here ]------------
+ kernel BUG at fs/btrfs/ctree.h:3357!
+ invalid opcode: 0000 [#1] SMP NOPTI
+ CPU: 0 PID: 24351 Comm: umount Tainted: G W 5.10.0-rc3+ #193
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
+ RIP: 0010:assertfail.constprop.0+0x18/0x1a
+ RSP: 0018:ffffa09b019c7e00 EFLAGS: 00010282
+ RAX: 0000000000000056 RBX: ffff8f6492c18000 RCX: 0000000000000000
+ RDX: ffff8f64fbc27c60 RSI: ffff8f64fbc19050 RDI: ffff8f64fbc19050
+ RBP: ffff8f6483bbdc00 R08: 0000000000000000 R09: 0000000000000000
+ R10: ffffa09b019c7c38 R11: ffffffff85d70928 R12: ffff8f6492c18100
+ R13: ffff8f6492c18148 R14: ffff8f6483bbdd70 R15: dead000000000100
+ FS: 00007fbfda4cdc40(0000) GS:ffff8f64fbc00000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00007fbfda666fd0 CR3: 000000013cf66002 CR4: 0000000000370ef0
+ Call Trace:
+ btrfs_free_block_groups.cold+0x55/0x55
+ close_ctree+0x2c5/0x306
+ ? fsnotify_destroy_marks+0x14/0x100
+ generic_shutdown_super+0x6c/0x100
+ kill_anon_super+0x14/0x30
+ btrfs_kill_super+0x12/0x20
+ deactivate_locked_super+0x36/0xa0
+ cleanup_mnt+0x12d/0x190
+ task_work_run+0x5c/0xa0
+ exit_to_user_mode_prepare+0x1b1/0x1d0
+ syscall_exit_to_user_mode+0x54/0x280
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+This happened because I injected an error in btrfs_cow_block() while
+running the dirty block groups. When we run the dirty block groups, we
+splice the list onto a local list to process. However if an error
+occurs, we only cleanup the transactions dirty block group list, not any
+pending block groups we have on our locally spliced list.
+
+In fact if we fail to allocate a path in this function we'll also fail
+to clean up the splice list.
+
+Fix this by splicing the list back onto the transaction dirty block
+group list so that the block groups are cleaned up. Then add a 'out'
+label and have the error conditions jump to out so that the errors are
+handled properly. This also has the side-effect of fixing a problem
+where we would clear 'ret' on error because we unconditionally ran
+btrfs_run_delayed_refs().
+
+CC: stable@vger.kernel.org # 4.4+
+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/block-group.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -2391,8 +2391,10 @@ again:
+
+ if (!path) {
+ path = btrfs_alloc_path();
+- if (!path)
+- return -ENOMEM;
++ if (!path) {
++ ret = -ENOMEM;
++ goto out;
++ }
+ }
+
+ /*
+@@ -2487,16 +2489,14 @@ again:
+ btrfs_put_block_group(cache);
+ if (drop_reserve)
+ btrfs_delayed_refs_rsv_release(fs_info, 1);
+-
+- if (ret)
+- break;
+-
+ /*
+ * Avoid blocking other tasks for too long. It might even save
+ * us from writing caches for block groups that are going to be
+ * removed.
+ */
+ mutex_unlock(&trans->transaction->cache_write_mutex);
++ if (ret)
++ goto out;
+ mutex_lock(&trans->transaction->cache_write_mutex);
+ }
+ mutex_unlock(&trans->transaction->cache_write_mutex);
+@@ -2520,7 +2520,12 @@ again:
+ goto again;
+ }
+ spin_unlock(&cur_trans->dirty_bgs_lock);
+- } else if (ret < 0) {
++ }
++out:
++ if (ret < 0) {
++ spin_lock(&cur_trans->dirty_bgs_lock);
++ list_splice_init(&dirty, &cur_trans->dirty_bgs);
++ spin_unlock(&cur_trans->dirty_bgs_lock);
+ btrfs_cleanup_dirty_bgs(cur_trans, fs_info);
+ }
+
--- /dev/null
+From a13ed1d15b07a04b1f74b2df61ff7a5e47f45dd8 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 4 Jan 2021 16:55:46 +0100
+Subject: crypto: aesni - prevent misaligned buffers on the stack
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+commit a13ed1d15b07a04b1f74b2df61ff7a5e47f45dd8 upstream.
+
+The GCM mode driver uses 16 byte aligned buffers on the stack to pass
+the IV to the asm helpers, but unfortunately, the x86 port does not
+guarantee that the stack pointer is 16 byte aligned upon entry in the
+first place. Since the compiler is not aware of this, it will not emit
+the additional stack realignment sequence that is needed, and so the
+alignment is not guaranteed to be more than 8 bytes.
+
+So instead, allocate some padding on the stack, and realign the IV
+pointer by hand.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/crypto/aesni-intel_glue.c | 28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+--- a/arch/x86/crypto/aesni-intel_glue.c
++++ b/arch/x86/crypto/aesni-intel_glue.c
+@@ -707,7 +707,8 @@ static int gcmaes_crypt_by_sg(bool enc,
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ unsigned long auth_tag_len = crypto_aead_authsize(tfm);
+ const struct aesni_gcm_tfm_s *gcm_tfm = aesni_gcm_tfm;
+- struct gcm_context_data data AESNI_ALIGN_ATTR;
++ u8 databuf[sizeof(struct gcm_context_data) + (AESNI_ALIGN - 8)] __aligned(8);
++ struct gcm_context_data *data = PTR_ALIGN((void *)databuf, AESNI_ALIGN);
+ struct scatter_walk dst_sg_walk = {};
+ unsigned long left = req->cryptlen;
+ unsigned long len, srclen, dstlen;
+@@ -760,8 +761,7 @@ static int gcmaes_crypt_by_sg(bool enc,
+ }
+
+ kernel_fpu_begin();
+- gcm_tfm->init(aes_ctx, &data, iv,
+- hash_subkey, assoc, assoclen);
++ gcm_tfm->init(aes_ctx, data, iv, hash_subkey, assoc, assoclen);
+ if (req->src != req->dst) {
+ while (left) {
+ src = scatterwalk_map(&src_sg_walk);
+@@ -771,10 +771,10 @@ static int gcmaes_crypt_by_sg(bool enc,
+ len = min(srclen, dstlen);
+ if (len) {
+ if (enc)
+- gcm_tfm->enc_update(aes_ctx, &data,
++ gcm_tfm->enc_update(aes_ctx, data,
+ dst, src, len);
+ else
+- gcm_tfm->dec_update(aes_ctx, &data,
++ gcm_tfm->dec_update(aes_ctx, data,
+ dst, src, len);
+ }
+ left -= len;
+@@ -792,10 +792,10 @@ static int gcmaes_crypt_by_sg(bool enc,
+ len = scatterwalk_clamp(&src_sg_walk, left);
+ if (len) {
+ if (enc)
+- gcm_tfm->enc_update(aes_ctx, &data,
++ gcm_tfm->enc_update(aes_ctx, data,
+ src, src, len);
+ else
+- gcm_tfm->dec_update(aes_ctx, &data,
++ gcm_tfm->dec_update(aes_ctx, data,
+ src, src, len);
+ }
+ left -= len;
+@@ -804,7 +804,7 @@ static int gcmaes_crypt_by_sg(bool enc,
+ scatterwalk_done(&src_sg_walk, 1, left);
+ }
+ }
+- gcm_tfm->finalize(aes_ctx, &data, authTag, auth_tag_len);
++ gcm_tfm->finalize(aes_ctx, data, authTag, auth_tag_len);
+ kernel_fpu_end();
+
+ if (!assocmem)
+@@ -853,7 +853,8 @@ static int helper_rfc4106_encrypt(struct
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+ void *aes_ctx = &(ctx->aes_key_expanded);
+- u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
++ u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
++ u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
+ unsigned int i;
+ __be32 counter = cpu_to_be32(1);
+
+@@ -880,7 +881,8 @@ static int helper_rfc4106_decrypt(struct
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
+ void *aes_ctx = &(ctx->aes_key_expanded);
+- u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
++ u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
++ u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
+ unsigned int i;
+
+ if (unlikely(req->assoclen != 16 && req->assoclen != 20))
+@@ -1010,7 +1012,8 @@ static int generic_gcmaes_encrypt(struct
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ struct generic_gcmaes_ctx *ctx = generic_gcmaes_ctx_get(tfm);
+ void *aes_ctx = &(ctx->aes_key_expanded);
+- u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
++ u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
++ u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
+ __be32 counter = cpu_to_be32(1);
+
+ memcpy(iv, req->iv, 12);
+@@ -1026,7 +1029,8 @@ static int generic_gcmaes_decrypt(struct
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+ struct generic_gcmaes_ctx *ctx = generic_gcmaes_ctx_get(tfm);
+ void *aes_ctx = &(ctx->aes_key_expanded);
+- u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
++ u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
++ u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
+
+ memcpy(iv, req->iv, 12);
+ *((__be32 *)(iv+12)) = counter;
--- /dev/null
+From 0df07d8117c3576f1603b05b84089742a118d10a Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Thu, 14 Jan 2021 19:10:10 +0100
+Subject: crypto: arm64/sha - add missing module aliases
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+commit 0df07d8117c3576f1603b05b84089742a118d10a upstream.
+
+The accelerated, instruction based implementations of SHA1, SHA2 and
+SHA3 are autoloaded based on CPU capabilities, given that the code is
+modest in size, and widely used, which means that resolving the algo
+name, loading all compatible modules and picking the one with the
+highest priority is taken to be suboptimal.
+
+However, if these algorithms are requested before this CPU feature
+based matching and autoloading occurs, these modules are not even
+considered, and we end up with suboptimal performance.
+
+So add the missing module aliases for the various SHA implementations.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/crypto/sha1-ce-glue.c | 1 +
+ arch/arm64/crypto/sha2-ce-glue.c | 2 ++
+ arch/arm64/crypto/sha3-ce-glue.c | 4 ++++
+ arch/arm64/crypto/sha512-ce-glue.c | 2 ++
+ 4 files changed, 9 insertions(+)
+
+--- a/arch/arm64/crypto/sha1-ce-glue.c
++++ b/arch/arm64/crypto/sha1-ce-glue.c
+@@ -19,6 +19,7 @@
+ MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
+ MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS_CRYPTO("sha1");
+
+ struct sha1_ce_state {
+ struct sha1_state sst;
+--- a/arch/arm64/crypto/sha2-ce-glue.c
++++ b/arch/arm64/crypto/sha2-ce-glue.c
+@@ -19,6 +19,8 @@
+ MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions");
+ MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS_CRYPTO("sha224");
++MODULE_ALIAS_CRYPTO("sha256");
+
+ struct sha256_ce_state {
+ struct sha256_state sst;
+--- a/arch/arm64/crypto/sha3-ce-glue.c
++++ b/arch/arm64/crypto/sha3-ce-glue.c
+@@ -23,6 +23,10 @@
+ MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions");
+ MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS_CRYPTO("sha3-224");
++MODULE_ALIAS_CRYPTO("sha3-256");
++MODULE_ALIAS_CRYPTO("sha3-384");
++MODULE_ALIAS_CRYPTO("sha3-512");
+
+ asmlinkage void sha3_ce_transform(u64 *st, const u8 *data, int blocks,
+ int md_len);
+--- a/arch/arm64/crypto/sha512-ce-glue.c
++++ b/arch/arm64/crypto/sha512-ce-glue.c
+@@ -23,6 +23,8 @@
+ MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions");
+ MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS_CRYPTO("sha384");
++MODULE_ALIAS_CRYPTO("sha512");
+
+ asmlinkage void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
+ int blocks);
--- /dev/null
+From 7bdcd851fa7eb66e8922aa7f6cba9e2f2427a7cf Mon Sep 17 00:00:00 2001
+From: Corentin Labbe <clabbe@baylibre.com>
+Date: Mon, 14 Dec 2020 20:02:26 +0000
+Subject: crypto: sun4i-ss - checking sg length is not sufficient
+
+From: Corentin Labbe <clabbe@baylibre.com>
+
+commit 7bdcd851fa7eb66e8922aa7f6cba9e2f2427a7cf upstream.
+
+The optimized cipher function need length multiple of 4 bytes.
+But it get sometimes odd length.
+This is due to SG data could be stored with an offset.
+
+So the fix is to check also if the offset is aligned with 4 bytes.
+Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+@@ -203,12 +203,12 @@ static int sun4i_ss_cipher_poll(struct s
+ * we can use the SS optimized function
+ */
+ while (in_sg && no_chunk == 1) {
+- if (in_sg->length % 4)
++ if ((in_sg->length | in_sg->offset) & 3u)
+ no_chunk = 0;
+ in_sg = sg_next(in_sg);
+ }
+ while (out_sg && no_chunk == 1) {
+- if (out_sg->length % 4)
++ if ((out_sg->length | out_sg->offset) & 3u)
+ no_chunk = 0;
+ out_sg = sg_next(out_sg);
+ }
--- /dev/null
+From 5ab6177fa02df15cd8a02a1f1fb361d2d5d8b946 Mon Sep 17 00:00:00 2001
+From: Corentin Labbe <clabbe@baylibre.com>
+Date: Mon, 14 Dec 2020 20:02:28 +0000
+Subject: crypto: sun4i-ss - handle BigEndian for cipher
+
+From: Corentin Labbe <clabbe@baylibre.com>
+
+commit 5ab6177fa02df15cd8a02a1f1fb361d2d5d8b946 upstream.
+
+Ciphers produce invalid results on BE.
+Key and IV need to be written in LE.
+
+Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+@@ -54,13 +54,13 @@ static int noinline_for_stack sun4i_ss_o
+
+ spin_lock_irqsave(&ss->slock, flags);
+
+- for (i = 0; i < op->keylen; i += 4)
+- writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
++ for (i = 0; i < op->keylen / 4; i++)
++ writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
+
+ if (areq->iv) {
+ for (i = 0; i < 4 && i < ivsize / 4; i++) {
+ v = *(u32 *)(areq->iv + i * 4);
+- writel(v, ss->base + SS_IV0 + i * 4);
++ writesl(ss->base + SS_IV0 + i * 4, &v, 1);
+ }
+ }
+ writel(mode, ss->base + SS_CTL);
+@@ -240,13 +240,13 @@ static int sun4i_ss_cipher_poll(struct s
+
+ spin_lock_irqsave(&ss->slock, flags);
+
+- for (i = 0; i < op->keylen; i += 4)
+- writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
++ for (i = 0; i < op->keylen / 4; i++)
++ writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
+
+ if (areq->iv) {
+ for (i = 0; i < 4 && i < ivsize / 4; i++) {
+ v = *(u32 *)(areq->iv + i * 4);
+- writel(v, ss->base + SS_IV0 + i * 4);
++ writesl(ss->base + SS_IV0 + i * 4, &v, 1);
+ }
+ }
+ writel(mode, ss->base + SS_CTL);
--- /dev/null
+From 4ec8977b921fd9d512701e009ce8082cb94b5c1c Mon Sep 17 00:00:00 2001
+From: Corentin Labbe <clabbe@baylibre.com>
+Date: Mon, 14 Dec 2020 20:02:29 +0000
+Subject: crypto: sun4i-ss - initialize need_fallback
+
+From: Corentin Labbe <clabbe@baylibre.com>
+
+commit 4ec8977b921fd9d512701e009ce8082cb94b5c1c upstream.
+
+The need_fallback is never initialized and seem to be always true at runtime.
+So all hardware operations are always bypassed.
+
+Fixes: 0ae1f46c55f87 ("crypto: sun4i-ss - fallback when length is not multiple of blocksize")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+@@ -196,7 +196,7 @@ static int sun4i_ss_cipher_poll(struct s
+ unsigned int obo = 0; /* offset in bufo*/
+ unsigned int obl = 0; /* length of data in bufo */
+ unsigned long flags;
+- bool need_fallback;
++ bool need_fallback = false;
+
+ if (!areq->cryptlen)
+ return 0;
--- /dev/null
+From b756f1c8fc9d84e3f546d7ffe056c5352f4aab05 Mon Sep 17 00:00:00 2001
+From: Corentin Labbe <clabbe@baylibre.com>
+Date: Mon, 14 Dec 2020 20:02:27 +0000
+Subject: crypto: sun4i-ss - IV register does not work on A10 and A13
+
+From: Corentin Labbe <clabbe@baylibre.com>
+
+commit b756f1c8fc9d84e3f546d7ffe056c5352f4aab05 upstream.
+
+Allwinner A10 and A13 SoC have a version of the SS which produce
+invalid IV in IVx register.
+
+Instead of adding a variant for those, let's convert SS to produce IV
+directly from data.
+Fixes: 6298e948215f2 ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 34 ++++++++++++++++++++++++------
+ 1 file changed, 28 insertions(+), 6 deletions(-)
+
+--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+@@ -20,6 +20,7 @@ static int noinline_for_stack sun4i_ss_o
+ unsigned int ivsize = crypto_skcipher_ivsize(tfm);
+ struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq);
+ u32 mode = ctx->mode;
++ void *backup_iv = NULL;
+ /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */
+ u32 rx_cnt = SS_RX_DEFAULT;
+ u32 tx_cnt = 0;
+@@ -44,6 +45,13 @@ static int noinline_for_stack sun4i_ss_o
+ return -EINVAL;
+ }
+
++ if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
++ backup_iv = kzalloc(ivsize, GFP_KERNEL);
++ if (!backup_iv)
++ return -ENOMEM;
++ scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
++ }
++
+ spin_lock_irqsave(&ss->slock, flags);
+
+ for (i = 0; i < op->keylen; i += 4)
+@@ -117,9 +125,12 @@ static int noinline_for_stack sun4i_ss_o
+ } while (oleft);
+
+ if (areq->iv) {
+- for (i = 0; i < 4 && i < ivsize / 4; i++) {
+- v = readl(ss->base + SS_IV0 + i * 4);
+- *(u32 *)(areq->iv + i * 4) = v;
++ if (mode & SS_DECRYPTION) {
++ memcpy(areq->iv, backup_iv, ivsize);
++ kfree_sensitive(backup_iv);
++ } else {
++ scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
++ ivsize, 0);
+ }
+ }
+
+@@ -176,6 +187,7 @@ static int sun4i_ss_cipher_poll(struct s
+ unsigned int ileft = areq->cryptlen;
+ unsigned int oleft = areq->cryptlen;
+ unsigned int todo;
++ void *backup_iv = NULL;
+ struct sg_mapping_iter mi, mo;
+ unsigned long pi = 0, po = 0; /* progress for in and out */
+ bool miter_err;
+@@ -219,6 +231,13 @@ static int sun4i_ss_cipher_poll(struct s
+ if (need_fallback)
+ return sun4i_ss_cipher_poll_fallback(areq);
+
++ if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) {
++ backup_iv = kzalloc(ivsize, GFP_KERNEL);
++ if (!backup_iv)
++ return -ENOMEM;
++ scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0);
++ }
++
+ spin_lock_irqsave(&ss->slock, flags);
+
+ for (i = 0; i < op->keylen; i += 4)
+@@ -347,9 +366,12 @@ static int sun4i_ss_cipher_poll(struct s
+ sg_miter_stop(&mo);
+ }
+ if (areq->iv) {
+- for (i = 0; i < 4 && i < ivsize / 4; i++) {
+- v = readl(ss->base + SS_IV0 + i * 4);
+- *(u32 *)(areq->iv + i * 4) = v;
++ if (mode & SS_DECRYPTION) {
++ memcpy(areq->iv, backup_iv, ivsize);
++ kfree_sensitive(backup_iv);
++ } else {
++ scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize,
++ ivsize, 0);
+ }
+ }
+
--- /dev/null
+From 2fd10bcf0310b9525b2af9e1f7aa9ddd87c3772e Mon Sep 17 00:00:00 2001
+From: Sabyrzhan Tasbolatov <snovitoll@gmail.com>
+Date: Tue, 9 Feb 2021 16:26:12 +0600
+Subject: drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
+
+From: Sabyrzhan Tasbolatov <snovitoll@gmail.com>
+
+commit 2fd10bcf0310b9525b2af9e1f7aa9ddd87c3772e upstream.
+
+syzbot found WARNING in qp_broker_alloc[1] in qp_host_alloc_queue()
+when num_pages is 0x100001, giving queue_size + queue_page_size
+bigger than KMALLOC_MAX_SIZE for kzalloc(), resulting order >= MAX_ORDER
+condition.
+
+queue_size + queue_page_size=0x8000d8, where KMALLOC_MAX_SIZE=0x400000.
+
+[1]
+Call Trace:
+ alloc_pages include/linux/gfp.h:547 [inline]
+ kmalloc_order+0x40/0x130 mm/slab_common.c:837
+ kmalloc_order_trace+0x15/0x70 mm/slab_common.c:853
+ kmalloc_large include/linux/slab.h:481 [inline]
+ __kmalloc+0x257/0x330 mm/slub.c:3959
+ kmalloc include/linux/slab.h:557 [inline]
+ kzalloc include/linux/slab.h:682 [inline]
+ qp_host_alloc_queue drivers/misc/vmw_vmci/vmci_queue_pair.c:540 [inline]
+ qp_broker_create drivers/misc/vmw_vmci/vmci_queue_pair.c:1351 [inline]
+ qp_broker_alloc+0x936/0x2740 drivers/misc/vmw_vmci/vmci_queue_pair.c:1739
+
+Reported-by: syzbot+15ec7391f3d6a1a7cc7d@syzkaller.appspotmail.com
+Signed-off-by: Sabyrzhan Tasbolatov <snovitoll@gmail.com>
+Link: https://lore.kernel.org/r/20210209102612.2112247-1-snovitoll@gmail.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/misc/vmw_vmci/vmci_queue_pair.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
++++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
+@@ -537,6 +537,9 @@ static struct vmci_queue *qp_host_alloc_
+
+ queue_page_size = num_pages * sizeof(*queue->kernel_if->u.h.page);
+
++ if (queue_size + queue_page_size > KMALLOC_MAX_SIZE)
++ return NULL;
++
+ queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL);
+ if (queue) {
+ queue->q_header = NULL;
--- /dev/null
+From 688f97ed3f5e339c0c2c09d9ee7ff23d5807b0a7 Mon Sep 17 00:00:00 2001
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Date: Fri, 5 Feb 2021 14:15:11 -0500
+Subject: drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit 688f97ed3f5e339c0c2c09d9ee7ff23d5807b0a7 upstream.
+
+When run igt@kms_vrr in a device that uses DCN2.1 architecture, we
+noticed multiple failures. Furthermore, when we tested a VRR demo, we
+noticed a system hang where the mouse pointer still works, but the
+entire system freezes; in this case, we don't see any dmesg warning or
+failure messages kernel. This happens due to a lack of vupdate_no_lock
+interrupt, making the userspace wait eternally to get the event back.
+For fixing this issue, we need to add the vupdate_no_lock interrupt in
+the interrupt list.
+
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c | 22 +++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
++++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+@@ -168,6 +168,11 @@ static const struct irq_source_info_func
+ .ack = NULL
+ };
+
++static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
++ .set = NULL,
++ .ack = NULL
++};
++
+ #undef BASE_INNER
+ #define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
+
+@@ -230,6 +235,17 @@ static const struct irq_source_info_func
+ .funcs = &vblank_irq_info_funcs\
+ }
+
++/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic
++ * of DCE's DC_IRQ_SOURCE_VUPDATEx.
++ */
++#define vupdate_no_lock_int_entry(reg_num)\
++ [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
++ IRQ_REG_ENTRY(OTG, reg_num,\
++ OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
++ OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
++ .funcs = &vupdate_no_lock_irq_info_funcs\
++ }
++
+ #define vblank_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
+ IRQ_REG_ENTRY(OTG, reg_num,\
+@@ -338,6 +354,12 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NU
+ vupdate_int_entry(3),
+ vupdate_int_entry(4),
+ vupdate_int_entry(5),
++ vupdate_no_lock_int_entry(0),
++ vupdate_no_lock_int_entry(1),
++ vupdate_no_lock_int_entry(2),
++ vupdate_no_lock_int_entry(3),
++ vupdate_no_lock_int_entry(4),
++ vupdate_no_lock_int_entry(5),
+ vblank_int_entry(0),
+ vblank_int_entry(1),
+ vblank_int_entry(2),
--- /dev/null
+From 6e80fb8ab04f6c4f377e2fd422bdd1855beb7371 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 16 Feb 2021 10:57:00 -0500
+Subject: drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 6e80fb8ab04f6c4f377e2fd422bdd1855beb7371 upstream.
+
+Fixes the rlc reference clock used for GPU timestamps.
+Value is 100Mhz. Confirmed with hardware team.
+
+v2: reword commit message.
+
+Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1480
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/soc15.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
++++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
+@@ -276,6 +276,8 @@ static u32 soc15_get_xclk(struct amdgpu_
+ {
+ u32 reference_clock = adev->clock.spll.reference_freq;
+
++ if (adev->asic_type == CHIP_RENOIR)
++ return 10000;
+ if (adev->asic_type == CHIP_RAVEN)
+ return reference_clock / 4;
+
--- /dev/null
+From d1f5a3fc85566e9ddce9361ef180f070367e6eab Mon Sep 17 00:00:00 2001
+From: Karol Herbst <kherbst@redhat.com>
+Date: Fri, 27 Nov 2020 19:39:09 +0100
+Subject: drm/nouveau/kms: handle mDP connectors
+
+From: Karol Herbst <kherbst@redhat.com>
+
+commit d1f5a3fc85566e9ddce9361ef180f070367e6eab upstream.
+
+In some cases we have the handle those explicitly as the fallback
+connector type detection fails and marks those as eDP connectors.
+
+Attempting to use such a connector with mutter leads to a crash of mutter
+as it ends up with two eDP displays.
+
+Information is taken from the official DCB documentation.
+
+Cc: stable@vger.kernel.org
+Cc: dri-devel@lists.freedesktop.org
+Cc: Ben Skeggs <bskeggs@redhat.com>
+Reported-by: Mark Pearson <markpearson@lenovo.com>
+Tested-by: Mark Pearson <markpearson@lenovo.com>
+Signed-off-by: Karol Herbst <kherbst@redhat.com>
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h | 1 +
+ drivers/gpu/drm/nouveau/nouveau_connector.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
+@@ -14,6 +14,7 @@ enum dcb_connector_type {
+ DCB_CONNECTOR_LVDS_SPWG = 0x41,
+ DCB_CONNECTOR_DP = 0x46,
+ DCB_CONNECTOR_eDP = 0x47,
++ DCB_CONNECTOR_mDP = 0x48,
+ DCB_CONNECTOR_HDMI_0 = 0x60,
+ DCB_CONNECTOR_HDMI_1 = 0x61,
+ DCB_CONNECTOR_HDMI_C = 0x63,
+--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
+@@ -1240,6 +1240,7 @@ drm_conntype_from_dcb(enum dcb_connector
+ case DCB_CONNECTOR_DMS59_DP0:
+ case DCB_CONNECTOR_DMS59_DP1:
+ case DCB_CONNECTOR_DP :
++ case DCB_CONNECTOR_mDP :
+ case DCB_CONNECTOR_USB_C : return DRM_MODE_CONNECTOR_DisplayPort;
+ case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP;
+ case DCB_CONNECTOR_HDMI_0 :
--- /dev/null
+From e582951baabba3e278c97169d0acc1e09b24a72e Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
+Date: Mon, 18 Jan 2021 16:01:13 -0500
+Subject: drm/sched: Cancel and flush all outstanding jobs before finish.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
+
+commit e582951baabba3e278c97169d0acc1e09b24a72e upstream.
+
+To avoid any possible use after free.
+
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/414814/
+CC: stable@vger.kernel.org
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/scheduler/sched_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/scheduler/sched_main.c
++++ b/drivers/gpu/drm/scheduler/sched_main.c
+@@ -851,6 +851,9 @@ void drm_sched_fini(struct drm_gpu_sched
+ if (sched->thread)
+ kthread_stop(sched->thread);
+
++ /* Confirm no work left behind accessing device structures */
++ cancel_delayed_work_sync(&sched->work_tdr);
++
+ sched->ready = false;
+ }
+ EXPORT_SYMBOL(drm_sched_fini);
--- /dev/null
+From dc2e76175417e69c41d927dba75a966399f18354 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Wed, 13 Jan 2021 19:09:19 +0100
+Subject: dts64: mt7622: fix slow sd card access
+
+From: Frank Wunderlich <frank-w@public-files.de>
+
+commit dc2e76175417e69c41d927dba75a966399f18354 upstream.
+
+Fix extreme slow speed (200MB takes ~20 min) on writing sdcard on
+bananapi-r64 by adding reset-control for mmc1 like it's done for mmc0/emmc.
+
+Fixes: 2c002a3049f7 ("arm64: dts: mt7622: add mmc related device nodes")
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210113180919.49523-1-linux@fw-web.de
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -698,6 +698,8 @@
+ clocks = <&pericfg CLK_PERI_MSDC30_1_PD>,
+ <&topckgen CLK_TOP_AXI_SEL>;
+ clock-names = "source", "hclk";
++ resets = <&pericfg MT7622_PERI_MSDC1_SW_RST>;
++ reset-names = "hrst";
+ status = "disabled";
+ };
+
--- /dev/null
+From ce063129181312f8781a047a50be439c5859747b Mon Sep 17 00:00:00 2001
+From: Gao Xiang <hsiangkao@redhat.com>
+Date: Tue, 9 Feb 2021 21:06:18 +0800
+Subject: erofs: initialized fields can only be observed after bit is set
+
+From: Gao Xiang <hsiangkao@redhat.com>
+
+commit ce063129181312f8781a047a50be439c5859747b upstream.
+
+Currently, although set_bit() & test_bit() pairs are used as a fast-
+path for initialized configurations. However, these atomic ops are
+actually relaxed forms. Instead, load-acquire & store-release form is
+needed to make sure uninitialized fields won't be observed in advance
+here (yet no such corresponding bitops so use full barriers instead.)
+
+Link: https://lore.kernel.org/r/20210209130618.15838-1-hsiangkao@aol.com
+Fixes: 62dc45979f3f ("staging: erofs: fix race of initializing xattrs of a inode at the same time")
+Fixes: 152a333a5895 ("staging: erofs: add compacted compression indexes support")
+Cc: <stable@vger.kernel.org> # 5.3+
+Reported-by: Huang Jianan <huangjianan@oppo.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Gao Xiang <hsiangkao@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/erofs/xattr.c | 10 +++++++++-
+ fs/erofs/zmap.c | 10 +++++++++-
+ 2 files changed, 18 insertions(+), 2 deletions(-)
+
+--- a/fs/erofs/xattr.c
++++ b/fs/erofs/xattr.c
+@@ -48,8 +48,14 @@ static int init_inode_xattrs(struct inod
+ int ret = 0;
+
+ /* the most case is that xattrs of this inode are initialized. */
+- if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags))
++ if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) {
++ /*
++ * paired with smp_mb() at the end of the function to ensure
++ * fields will only be observed after the bit is set.
++ */
++ smp_mb();
+ return 0;
++ }
+
+ if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_XATTR_BIT, TASK_KILLABLE))
+ return -ERESTARTSYS;
+@@ -137,6 +143,8 @@ static int init_inode_xattrs(struct inod
+ }
+ xattr_iter_end(&it, atomic_map);
+
++ /* paired with smp_mb() at the beginning of the function. */
++ smp_mb();
+ set_bit(EROFS_I_EA_INITED_BIT, &vi->flags);
+
+ out_unlock:
+--- a/fs/erofs/zmap.c
++++ b/fs/erofs/zmap.c
+@@ -36,8 +36,14 @@ static int fill_inode_lazy(struct inode
+ void *kaddr;
+ struct z_erofs_map_header *h;
+
+- if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags))
++ if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) {
++ /*
++ * paired with smp_mb() at the end of the function to ensure
++ * fields will only be observed after the bit is set.
++ */
++ smp_mb();
+ return 0;
++ }
+
+ if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_Z_BIT, TASK_KILLABLE))
+ return -ERESTARTSYS;
+@@ -83,6 +89,8 @@ static int fill_inode_lazy(struct inode
+
+ vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits +
+ ((h->h_clusterbits >> 5) & 7);
++ /* paired with smp_mb() at the beginning of the function */
++ smp_mb();
+ set_bit(EROFS_I_Z_INITED_BIT, &vi->flags);
+ unmap_done:
+ kunmap_atomic(kaddr);
--- /dev/null
+From ef07c116d98772952807492bd32a61f5af172a94 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Filipe=20La=C3=ADns?= <lains@riseup.net>
+Date: Fri, 5 Feb 2021 14:34:44 +0000
+Subject: HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Filipe Laíns <lains@riseup.net>
+
+commit ef07c116d98772952807492bd32a61f5af172a94 upstream.
+
+In e400071a805d6229223a98899e9da8c6233704a1 I added support for the
+receiver that comes with the G602 device, but unfortunately I screwed up
+during testing and it seems the keyboard events were actually not being
+sent to userspace.
+This resulted in keyboard events being broken in userspace, please
+backport the fix.
+
+The receiver uses the normal 0x01 Logitech keyboard report descriptor,
+as expected, so it is just a matter of flagging it as supported.
+
+Reported in
+https://github.com/libratbag/libratbag/issues/1124
+
+Fixes: e400071a805d6 ("HID: logitech-dj: add the G602 receiver")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Filipe Laíns <lains@riseup.net>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-logitech-dj.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/hid/hid-logitech-dj.c
++++ b/drivers/hid/hid-logitech-dj.c
+@@ -980,6 +980,7 @@ static void logi_hidpp_recv_queue_notif(
+ case 0x07:
+ device_type = "eQUAD step 4 Gaming";
+ logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
++ workitem.reports_supported |= STD_KEYBOARD;
+ break;
+ case 0x08:
+ device_type = "eQUAD step 4 for gamepads";
--- /dev/null
+From 88f38846bfb1a452a3d47e38aeab20a4ceb74294 Mon Sep 17 00:00:00 2001
+From: Jason Gerecke <killertofu@gmail.com>
+Date: Tue, 16 Feb 2021 11:41:54 -0800
+Subject: HID: wacom: Ignore attempts to overwrite the touch_max value from HID
+
+From: Jason Gerecke <killertofu@gmail.com>
+
+commit 88f38846bfb1a452a3d47e38aeab20a4ceb74294 upstream.
+
+The `wacom_feature_mapping` function is careful to only set the the
+touch_max value a single time, but this care does not extend to the
+`wacom_wac_finger_event` function. In particular, if a device sends
+multiple HID_DG_CONTACTMAX items in a single feature report, the
+driver will end up retaining the value of last item.
+
+The HID descriptor for the Cintiq Companion 2 does exactly this. It
+incorrectly sets a "Report Count" of 2, which will cause the driver
+to process two HID_DG_CONTACTCOUNT items. The first item has the actual
+count, while the second item should have been declared as a constant
+zero. The constant zero is the value the driver ends up using, however,
+since it is the last HID_DG_CONTACTCOUNT in the report.
+
+ Report ID (16),
+ Usage (Contact Count Maximum), ; Contact count maximum (55h, static value)
+ Report Count (2),
+ Logical Maximum (10),
+ Feature (Variable),
+
+To address this, we add a check that the touch_max is not already set
+within the `wacom_wac_finger_event` function that processes the
+HID_DG_TOUCHMAX item. We emit a warning if the value is set and ignore
+the updated value.
+
+This could potentially cause problems if there is a tablet which has
+a similar issue but requires the last item to be used. This is unlikely,
+however, since it would have to have a different non-zero value for
+HID_DG_CONTACTMAX earlier in the same report, which makes no sense
+except in the case of a firmware bug. Note that cases where the
+HID_DG_CONTACTMAX items are in different reports is already handled
+(and similarly ignored) by `wacom_feature_mapping` as mentioned above.
+
+Link: https://github.com/linuxwacom/input-wacom/issues/223
+Fixes: 184eccd40389 ("HID: wacom: generic: read HID_DG_CONTACTMAX from any feature report")
+Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
+CC: stable@vger.kernel.org
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/wacom_wac.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -2600,7 +2600,12 @@ static void wacom_wac_finger_event(struc
+ wacom_wac->is_invalid_bt_frame = !value;
+ return;
+ case HID_DG_CONTACTMAX:
+- features->touch_max = value;
++ if (!features->touch_max) {
++ features->touch_max = value;
++ } else {
++ hid_warn(hdev, "%s: ignoring attempt to overwrite non-zero touch_max "
++ "%d -> %d\n", __func__, features->touch_max, value);
++ }
+ return;
+ }
+
--- /dev/null
+From b5d6e7ab7fe7d186878142e9fc1a05e4c3b65eb9 Mon Sep 17 00:00:00 2001
+From: Marcos Paulo de Souza <mpdesouza@suse.com>
+Date: Fri, 19 Feb 2021 10:37:13 -0800
+Subject: Input: i8042 - add ASUS Zenbook Flip to noselftest list
+
+From: Marcos Paulo de Souza <mpdesouza@suse.com>
+
+commit b5d6e7ab7fe7d186878142e9fc1a05e4c3b65eb9 upstream.
+
+After commit 77b425399f6d ("Input: i8042 - use chassis info to skip
+selftest on Asus laptops"), all modern Asus laptops have the i8042
+selftest disabled. It has done by using chassys type "10" (laptop).
+
+The Asus Zenbook Flip suffers from similar suspend/resume issues, but
+it _sometimes_ work and sometimes it doesn't. Setting noselftest makes
+it work reliably. In this case, we need to add chassis type "31"
+(convertible) in order to avoid selftest in this device.
+
+Reported-by: Ludvig Norgren Guldhag <ludvigng@gmail.com>
+Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
+Link: https://lore.kernel.org/r/20210219164638.761-1-mpdesouza@suse.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/serio/i8042-x86ia64io.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -588,6 +588,10 @@ static const struct dmi_system_id i8042_
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+ },
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */
++ },
+ },
+ { }
+ };
--- /dev/null
+From 182d679b2298d62bf42bb14b12a8067b8e17b617 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 17 Feb 2021 12:21:10 -0800
+Subject: Input: joydev - prevent potential read overflow in ioctl
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 182d679b2298d62bf42bb14b12a8067b8e17b617 upstream.
+
+The problem here is that "len" might be less than "joydev->nabs" so the
+loops which verfy abspam[i] and keypam[] might read beyond the buffer.
+
+Fixes: 999b874f4aa3 ("Input: joydev - validate axis/button maps before clobbering current ones")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Link: https://lore.kernel.org/r/YCyzR8WvFRw4HWw6@mwanda
+[dtor: additional check for len being even in joydev_handle_JSIOCSBTNMAP]
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/joydev.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/input/joydev.c
++++ b/drivers/input/joydev.c
+@@ -456,7 +456,7 @@ static int joydev_handle_JSIOCSAXMAP(str
+ if (IS_ERR(abspam))
+ return PTR_ERR(abspam);
+
+- for (i = 0; i < joydev->nabs; i++) {
++ for (i = 0; i < len && i < joydev->nabs; i++) {
+ if (abspam[i] > ABS_MAX) {
+ retval = -EINVAL;
+ goto out;
+@@ -480,6 +480,9 @@ static int joydev_handle_JSIOCSBTNMAP(st
+ int i;
+ int retval = 0;
+
++ if (len % sizeof(*keypam))
++ return -EINVAL;
++
+ len = min(len, sizeof(joydev->keypam));
+
+ /* Validate the map. */
+@@ -487,7 +490,7 @@ static int joydev_handle_JSIOCSBTNMAP(st
+ if (IS_ERR(keypam))
+ return PTR_ERR(keypam);
+
+- for (i = 0; i < joydev->nkey; i++) {
++ for (i = 0; i < (len / 2) && i < joydev->nkey; i++) {
+ if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
+ retval = -EINVAL;
+ goto out;
--- /dev/null
+From fafd320ae51b9c72d371585b2501f86640ea7b7d Mon Sep 17 00:00:00 2001
+From: "jeffrey.lin" <jeffrey.lin@rad-ic.com>
+Date: Tue, 15 Dec 2020 10:50:12 -0800
+Subject: Input: raydium_ts_i2c - do not send zero length
+
+From: jeffrey.lin <jeffrey.lin@rad-ic.com>
+
+commit fafd320ae51b9c72d371585b2501f86640ea7b7d upstream.
+
+Add default write command package to prevent i2c quirk error of zero
+data length as Raydium touch firmware update is executed.
+
+Signed-off-by: jeffrey.lin <jeffrey.lin@rad-ic.com>
+Link: https://lore.kernel.org/r/1608031217-7247-1-git-send-email-jeffrey.lin@raydium.corp-partner.google.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/touchscreen/raydium_i2c_ts.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/input/touchscreen/raydium_i2c_ts.c
++++ b/drivers/input/touchscreen/raydium_i2c_ts.c
+@@ -410,6 +410,7 @@ static int raydium_i2c_write_object(stru
+ enum raydium_bl_ack state)
+ {
+ int error;
++ static const u8 cmd[] = { 0xFF, 0x39 };
+
+ error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len);
+ if (error) {
+@@ -418,7 +419,7 @@ static int raydium_i2c_write_object(stru
+ return error;
+ }
+
+- error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, NULL, 0);
++ error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, cmd, sizeof(cmd));
+ if (error) {
+ dev_err(&client->dev, "Ack obj command failed: %d\n", error);
+ return error;
--- /dev/null
+From 42ffcd1dba1796bcda386eb6f260df9fc23c90af Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= <olivier.crete@ocrete.ca>
+Date: Fri, 5 Feb 2021 11:59:08 -0800
+Subject: Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Olivier Crête <olivier.crete@ocrete.ca>
+
+commit 42ffcd1dba1796bcda386eb6f260df9fc23c90af upstream.
+
+Signed-off-by: Olivier Crête <olivier.crete@ocrete.ca>
+Link: https://lore.kernel.org/r/20210204005318.615647-1-olivier.crete@collabora.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/joystick/xpad.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -305,6 +305,7 @@ static const struct xpad_device {
+ { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
+ { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
+ { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
++ { 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
+ { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
+ { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
+ { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
--- /dev/null
+From 8da7520c80468c48f981f0b81fc1be6599e3b0ad Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko@kernel.org>
+Date: Fri, 29 Jan 2021 01:56:20 +0200
+Subject: KEYS: trusted: Fix migratable=1 failing
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+commit 8da7520c80468c48f981f0b81fc1be6599e3b0ad upstream.
+
+Consider the following transcript:
+
+$ keyctl add trusted kmk "new 32 blobauth=helloworld keyhandle=80000000 migratable=1" @u
+add_key: Invalid argument
+
+The documentation has the following description:
+
+ migratable= 0|1 indicating permission to reseal to new PCR values,
+ default 1 (resealing allowed)
+
+The consequence is that "migratable=1" should succeed. Fix this by
+allowing this condition to pass instead of return -EINVAL.
+
+[*] Documentation/security/keys/trusted-encrypted.rst
+
+Cc: stable@vger.kernel.org
+Cc: "James E.J. Bottomley" <jejb@linux.ibm.com>
+Cc: Mimi Zohar <zohar@linux.ibm.com>
+Cc: David Howells <dhowells@redhat.com>
+Fixes: d00a1c72f7f4 ("keys: add new trusted key-type")
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/keys/trusted.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/security/keys/trusted.c
++++ b/security/keys/trusted.c
+@@ -805,7 +805,7 @@ static int getoptions(char *c, struct tr
+ case Opt_migratable:
+ if (*args[0].from == '0')
+ pay->migratable = 0;
+- else
++ else if (*args[0].from != '1')
+ return -EINVAL;
+ break;
+ case Opt_pcrlock:
--- /dev/null
+From 1b43bad31fb0e00f45baf5b05bd21eb8d8ce7f58 Mon Sep 17 00:00:00 2001
+From: James Reynolds <jr@memlen.com>
+Date: Tue, 22 Dec 2020 13:07:04 +0100
+Subject: media: mceusb: Fix potential out-of-bounds shift
+
+From: James Reynolds <jr@memlen.com>
+
+commit 1b43bad31fb0e00f45baf5b05bd21eb8d8ce7f58 upstream.
+
+When processing a MCE_RSP_GETPORTSTATUS command, the bit index to set in
+ir->txports_cabled comes from response data, and isn't validated.
+
+As ir->txports_cabled is a u8, nothing should be done if the bit index
+is greater than 7.
+
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+ec3b3128c576e109171d@syzkaller.appspotmail.com
+Signed-off-by: James Reynolds <jr@memlen.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/rc/mceusb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -1169,7 +1169,7 @@ static void mceusb_handle_command(struct
+ switch (subcmd) {
+ /* the one and only 5-byte return value command */
+ case MCE_RSP_GETPORTSTATUS:
+- if (buf_in[5] == 0)
++ if (buf_in[5] == 0 && *hi < 8)
+ ir->txports_cabled |= 1 << *hi;
+ break;
+
--- /dev/null
+From 920fd8a70619074eac7687352c8f1c6f3c2a64a5 Mon Sep 17 00:00:00 2001
+From: Ricky Wu <ricky_wu@realtek.com>
+Date: Thu, 4 Feb 2021 16:31:15 +0800
+Subject: misc: rtsx: init of rts522a add OCP power off when no card is present
+
+From: Ricky Wu <ricky_wu@realtek.com>
+
+commit 920fd8a70619074eac7687352c8f1c6f3c2a64a5 upstream.
+
+Power down OCP for power consumption
+when no SD/MMC card is present
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Ricky Wu <ricky_wu@realtek.com>
+Link: https://lore.kernel.org/r/20210204083115.9471-1-ricky_wu@realtek.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/misc/cardreader/rts5227.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/misc/cardreader/rts5227.c
++++ b/drivers/misc/cardreader/rts5227.c
+@@ -338,6 +338,11 @@ static int rts522a_extra_init_hw(struct
+ {
+ rts5227_extra_init_hw(pcr);
+
++ /* Power down OCP for power consumption */
++ if (!pcr->card_exist)
++ rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
++ OC_POWER_DOWN);
++
+ rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
+ FUNC_FORCE_UPME_XMT_DBG);
+ rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
--- /dev/null
+From 19d8e9149c27b689c6224f5c84b96a159342195a Mon Sep 17 00:00:00 2001
+From: Jiri Bohac <jbohac@suse.cz>
+Date: Thu, 18 Feb 2021 12:15:47 +0100
+Subject: pstore: Fix typo in compression option name
+
+From: Jiri Bohac <jbohac@suse.cz>
+
+commit 19d8e9149c27b689c6224f5c84b96a159342195a upstream.
+
+Both pstore_compress() and decompress_record() use a mistyped config
+option name ("PSTORE_COMPRESSION" instead of "PSTORE_COMPRESS"). As
+a result compression and decompression of pstore records was always
+disabled.
+
+Use the correct config option name.
+
+Signed-off-by: Jiri Bohac <jbohac@suse.cz>
+Fixes: fd49e03280e5 ("pstore: Fix linking when crypto API disabled")
+Acked-by: Matteo Croce <mcroce@microsoft.com>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210218111547.johvp5klpv3xrpnn@dwarf.suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/pstore/platform.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/pstore/platform.c
++++ b/fs/pstore/platform.c
+@@ -275,7 +275,7 @@ static int pstore_compress(const void *i
+ {
+ int ret;
+
+- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESSION))
++ if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS))
+ return -EINVAL;
+
+ ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
+@@ -664,7 +664,7 @@ static void decompress_record(struct pst
+ int unzipped_len;
+ char *unzipped, *workspace;
+
+- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESSION) || !record->compressed)
++ if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed)
+ return;
+
+ /* Only PSTORE_TYPE_DMESG support compression. */
--- /dev/null
+From 9f233ffe02e5cef611100cd8c5bcf4de26ca7bef Mon Sep 17 00:00:00 2001
+From: Kai Krakow <kai@kaishome.de>
+Date: Wed, 10 Feb 2021 13:07:25 +0800
+Subject: Revert "bcache: Kill btree_io_wq"
+
+From: Kai Krakow <kai@kaishome.de>
+
+commit 9f233ffe02e5cef611100cd8c5bcf4de26ca7bef upstream.
+
+This reverts commit 56b30770b27d54d68ad51eccc6d888282b568cee.
+
+With the btree using the `system_wq`, I seem to see a lot more desktop
+latency than I should.
+
+After some more investigation, it looks like the original assumption
+of 56b3077 no longer is true, and bcache has a very high potential of
+congesting the `system_wq`. In turn, this introduces laggy desktop
+performance, IO stalls (at least with btrfs), and input events may be
+delayed.
+
+So let's revert this. It's important to note that the semantics of
+using `system_wq` previously mean that `btree_io_wq` should be created
+before and destroyed after other bcache wqs to keep the same
+assumptions.
+
+Cc: Coly Li <colyli@suse.de>
+Cc: stable@vger.kernel.org # 5.4+
+Signed-off-by: Kai Krakow <kai@kaishome.de>
+Signed-off-by: Coly Li <colyli@suse.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/bcache/bcache.h | 2 ++
+ drivers/md/bcache/btree.c | 21 +++++++++++++++++++--
+ drivers/md/bcache/super.c | 4 ++++
+ 3 files changed, 25 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/bcache/bcache.h
++++ b/drivers/md/bcache/bcache.h
+@@ -1027,5 +1027,7 @@ void bch_debug_exit(void);
+ void bch_debug_init(void);
+ void bch_request_exit(void);
+ int bch_request_init(void);
++void bch_btree_exit(void);
++int bch_btree_init(void);
+
+ #endif /* _BCACHE_H */
+--- a/drivers/md/bcache/btree.c
++++ b/drivers/md/bcache/btree.c
+@@ -99,6 +99,8 @@
+ #define PTR_HASH(c, k) \
+ (((k)->ptr[0] >> c->bucket_bits) | PTR_GEN(k, 0))
+
++static struct workqueue_struct *btree_io_wq;
++
+ #define insert_lock(s, b) ((b)->level <= (s)->lock)
+
+ /*
+@@ -366,7 +368,7 @@ static void __btree_node_write_done(stru
+ btree_complete_write(b, w);
+
+ if (btree_node_dirty(b))
+- schedule_delayed_work(&b->work, 30 * HZ);
++ queue_delayed_work(btree_io_wq, &b->work, 30 * HZ);
+
+ closure_return_with_destructor(cl, btree_node_write_unlock);
+ }
+@@ -539,7 +541,7 @@ static void bch_btree_leaf_dirty(struct
+ BUG_ON(!i->keys);
+
+ if (!btree_node_dirty(b))
+- schedule_delayed_work(&b->work, 30 * HZ);
++ queue_delayed_work(btree_io_wq, &b->work, 30 * HZ);
+
+ set_btree_node_dirty(b);
+
+@@ -2659,3 +2661,18 @@ void bch_keybuf_init(struct keybuf *buf)
+ spin_lock_init(&buf->lock);
+ array_allocator_init(&buf->freelist);
+ }
++
++void bch_btree_exit(void)
++{
++ if (btree_io_wq)
++ destroy_workqueue(btree_io_wq);
++}
++
++int __init bch_btree_init(void)
++{
++ btree_io_wq = create_singlethread_workqueue("bch_btree_io");
++ if (!btree_io_wq)
++ return -ENOMEM;
++
++ return 0;
++}
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -2652,6 +2652,7 @@ static void bcache_exit(void)
+ destroy_workqueue(bcache_wq);
+ if (bch_journal_wq)
+ destroy_workqueue(bch_journal_wq);
++ bch_btree_exit();
+
+ if (bcache_major)
+ unregister_blkdev(bcache_major, "bcache");
+@@ -2707,6 +2708,9 @@ static int __init bcache_init(void)
+ return bcache_major;
+ }
+
++ if (bch_btree_init())
++ goto err;
++
+ bcache_wq = alloc_workqueue("bcache", WQ_MEM_RECLAIM, 0);
+ if (!bcache_wq)
+ goto err;
--- /dev/null
+From 04b38d012556199ba4c31195940160e0c44c64f0 Mon Sep 17 00:00:00 2001
+From: Paul Cercueil <paul@crapouillou.net>
+Date: Mon, 11 Jan 2021 17:28:39 +0000
+Subject: seccomp: Add missing return in non-void function
+
+From: Paul Cercueil <paul@crapouillou.net>
+
+commit 04b38d012556199ba4c31195940160e0c44c64f0 upstream.
+
+We don't actually care about the value, since the kernel will panic
+before that; but a value should nonetheless be returned, otherwise the
+compiler will complain.
+
+Fixes: 8112c4f140fa ("seccomp: remove 2-phase API")
+Cc: stable@vger.kernel.org # 4.7+
+Signed-off-by: Paul Cercueil <paul@crapouillou.net>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Link: https://lore.kernel.org/r/20210111172839.640914-1-paul@crapouillou.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/seccomp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -921,6 +921,8 @@ static int __seccomp_filter(int this_sys
+ const bool recheck_after_trace)
+ {
+ BUG();
++
++ return -1;
+ }
+ #endif
+
i2c-brcmstb-fix-brcmstd_send_i2c_cmd-condition.patch
mm-rmap-fix-potential-pte_unmap-on-an-not-mapped-pte.patch
scsi-bnx2fc-fix-kconfig-warning-cnic-build-errors.patch
+blk-settings-align-max_sectors-on-logical_block_size-boundary.patch
+acpi-property-fix-fwnode-string-properties-matching.patch
+acpi-configfs-add-missing-check-after-configfs_register_default_group.patch
+hid-logitech-dj-add-support-for-keyboard-events-in-equad-step-4-gaming.patch
+hid-wacom-ignore-attempts-to-overwrite-the-touch_max-value-from-hid.patch
+input-raydium_ts_i2c-do-not-send-zero-length.patch
+input-xpad-add-support-for-powera-enhanced-wired-controller-for-xbox-series-x-s.patch
+input-joydev-prevent-potential-read-overflow-in-ioctl.patch
+input-i8042-add-asus-zenbook-flip-to-noselftest-list.patch
+media-mceusb-fix-potential-out-of-bounds-shift.patch
+usb-serial-option-update-interface-mapping-for-zte-p685m.patch
+usb-musb-fix-runtime-pm-race-in-musb_queue_resume_work.patch
+usb-dwc3-gadget-fix-setting-of-depcfg.binterval_m1.patch
+usb-dwc3-gadget-fix-dep-interval-for-fullspeed-interrupt.patch
+usb-serial-ftdi_sio-fix-ftx-sub-integer-prescaler.patch
+usb-serial-mos7840-fix-error-code-in-mos7840_write.patch
+usb-serial-mos7720-fix-error-code-in-mos7720_write.patch
+alsa-hda-add-another-cometlake-h-pci-id.patch
+alsa-hda-realtek-modify-eapd-in-the-alc886.patch
+revert-bcache-kill-btree_io_wq.patch
+bcache-give-btree_io_wq-correct-semantics-again.patch
+bcache-move-journal-work-to-new-flush-wq.patch
+drm-amd-display-add-vupdate_no_lock-interrupts-for-dcn2.1.patch
+drm-amdgpu-set-reference-clock-to-100mhz-on-renoir-v2.patch
+drm-nouveau-kms-handle-mdp-connectors.patch
+drm-sched-cancel-and-flush-all-outstanding-jobs-before-finish.patch
+erofs-initialized-fields-can-only-be-observed-after-bit-is-set.patch
+tpm_tis-fix-check_locality-for-correct-locality-acquisition.patch
+tpm_tis-clean-up-locality-release.patch
+keys-trusted-fix-migratable-1-failing.patch
+btrfs-abort-the-transaction-if-we-fail-to-inc-ref-in-btrfs_copy_root.patch
+btrfs-fix-reloc-root-leak-with-0-ref-reloc-roots-on-recovery.patch
+btrfs-splice-remaining-dirty_bg-s-onto-the-transaction-dirty-bg-list.patch
+btrfs-fix-extent-buffer-leak-on-failure-to-copy-root.patch
+crypto-arm64-sha-add-missing-module-aliases.patch
+crypto-aesni-prevent-misaligned-buffers-on-the-stack.patch
+crypto-sun4i-ss-checking-sg-length-is-not-sufficient.patch
+crypto-sun4i-ss-iv-register-does-not-work-on-a10-and-a13.patch
+crypto-sun4i-ss-handle-bigendian-for-cipher.patch
+crypto-sun4i-ss-initialize-need_fallback.patch
+seccomp-add-missing-return-in-non-void-function.patch
+misc-rtsx-init-of-rts522a-add-ocp-power-off-when-no-card-is-present.patch
+drivers-misc-vmw_vmci-restrict-too-big-queue-size-in-qp_host_alloc_queue.patch
+pstore-fix-typo-in-compression-option-name.patch
+dts64-mt7622-fix-slow-sd-card-access.patch
+staging-mt7621-dma-mtk-hsdma.c-hsdma-mt7621.c.patch
+staging-gdm724x-fix-dma-from-stack.patch
+staging-rtl8188eu-add-edimax-ew-7811un-v2-to-device-table.patch
--- /dev/null
+From 7c3a0635cd008eaca9a734dc802709ee0b81cac5 Mon Sep 17 00:00:00 2001
+From: Amey Narkhede <ameynarkhede03@gmail.com>
+Date: Thu, 11 Feb 2021 11:08:19 +0530
+Subject: staging: gdm724x: Fix DMA from stack
+
+From: Amey Narkhede <ameynarkhede03@gmail.com>
+
+commit 7c3a0635cd008eaca9a734dc802709ee0b81cac5 upstream.
+
+Stack allocated buffers cannot be used for DMA
+on all architectures so allocate hci_packet buffer
+using kmalloc.
+
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Amey Narkhede <ameynarkhede03@gmail.com>
+Link: https://lore.kernel.org/r/20210211053819.34858-1-ameynarkhede03@gmail.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/gdm724x/gdm_usb.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/gdm724x/gdm_usb.c
++++ b/drivers/staging/gdm724x/gdm_usb.c
+@@ -56,20 +56,24 @@ static int gdm_usb_recv(void *priv_dev,
+
+ static int request_mac_address(struct lte_udev *udev)
+ {
+- u8 buf[16] = {0,};
+- struct hci_packet *hci = (struct hci_packet *)buf;
++ struct hci_packet *hci;
+ struct usb_device *usbdev = udev->usbdev;
+ int actual;
+ int ret = -1;
+
++ hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL);
++ if (!hci)
++ return -ENOMEM;
++
+ hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION);
+ hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1);
+ hci->data[0] = MAC_ADDRESS;
+
+- ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), buf, 5,
++ ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5,
+ &actual, 1000);
+
+ udev->request_mac_addr = 1;
++ kfree(hci);
+
+ return ret;
+ }
--- /dev/null
+From 1f92798cbe7fe923479cff754dd06dd23d352e36 Mon Sep 17 00:00:00 2001
+From: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+Date: Fri, 29 Jan 2021 19:45:07 -0800
+Subject: staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
+
+From: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+
+commit 1f92798cbe7fe923479cff754dd06dd23d352e36 upstream.
+
+Also use KBUILD_MODNAME for module name.
+
+This driver is only used by RALINK MIPS MT7621 SoCs. Tested by building
+against that target using OpenWrt with Linux 5.10.10.
+
+Fixes the following error:
+error: the following would cause module name conflict:
+ drivers/dma/mediatek/mtk-hsdma.ko
+ drivers/staging/mt7621-dma/mtk-hsdma.ko
+
+Cc: stable@vger.kernel.org
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+Link: https://lore.kernel.org/r/20210130034507.2115280-1-ilya.lipnitskiy@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/mt7621-dma/Makefile | 2
+ drivers/staging/mt7621-dma/hsdma-mt7621.c | 762 ++++++++++++++++++++++++++++++
+ drivers/staging/mt7621-dma/mtk-hsdma.c | 762 ------------------------------
+ 3 files changed, 763 insertions(+), 763 deletions(-)
+ rename drivers/staging/mt7621-dma/{mtk-hsdma.c => hsdma-mt7621.c} (99%)
+
+--- a/drivers/staging/mt7621-dma/Makefile
++++ b/drivers/staging/mt7621-dma/Makefile
+@@ -1,4 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0
+-obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o
++obj-$(CONFIG_MTK_HSDMA) += hsdma-mt7621.o
+
+ ccflags-y += -I$(srctree)/drivers/dma
+--- /dev/null
++++ b/drivers/staging/mt7621-dma/hsdma-mt7621.c
+@@ -0,0 +1,762 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2015, Michael Lee <igvtee@gmail.com>
++ * MTK HSDMA support
++ */
++
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/irq.h>
++#include <linux/of_dma.h>
++#include <linux/reset.h>
++#include <linux/of_device.h>
++
++#include "virt-dma.h"
++
++#define HSDMA_BASE_OFFSET 0x800
++
++#define HSDMA_REG_TX_BASE 0x00
++#define HSDMA_REG_TX_CNT 0x04
++#define HSDMA_REG_TX_CTX 0x08
++#define HSDMA_REG_TX_DTX 0x0c
++#define HSDMA_REG_RX_BASE 0x100
++#define HSDMA_REG_RX_CNT 0x104
++#define HSDMA_REG_RX_CRX 0x108
++#define HSDMA_REG_RX_DRX 0x10c
++#define HSDMA_REG_INFO 0x200
++#define HSDMA_REG_GLO_CFG 0x204
++#define HSDMA_REG_RST_CFG 0x208
++#define HSDMA_REG_DELAY_INT 0x20c
++#define HSDMA_REG_FREEQ_THRES 0x210
++#define HSDMA_REG_INT_STATUS 0x220
++#define HSDMA_REG_INT_MASK 0x228
++#define HSDMA_REG_SCH_Q01 0x280
++#define HSDMA_REG_SCH_Q23 0x284
++
++#define HSDMA_DESCS_MAX 0xfff
++#define HSDMA_DESCS_NUM 8
++#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1)
++#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK)
++
++/* HSDMA_REG_INFO */
++#define HSDMA_INFO_INDEX_MASK 0xf
++#define HSDMA_INFO_INDEX_SHIFT 24
++#define HSDMA_INFO_BASE_MASK 0xff
++#define HSDMA_INFO_BASE_SHIFT 16
++#define HSDMA_INFO_RX_MASK 0xff
++#define HSDMA_INFO_RX_SHIFT 8
++#define HSDMA_INFO_TX_MASK 0xff
++#define HSDMA_INFO_TX_SHIFT 0
++
++/* HSDMA_REG_GLO_CFG */
++#define HSDMA_GLO_TX_2B_OFFSET BIT(31)
++#define HSDMA_GLO_CLK_GATE BIT(30)
++#define HSDMA_GLO_BYTE_SWAP BIT(29)
++#define HSDMA_GLO_MULTI_DMA BIT(10)
++#define HSDMA_GLO_TWO_BUF BIT(9)
++#define HSDMA_GLO_32B_DESC BIT(8)
++#define HSDMA_GLO_BIG_ENDIAN BIT(7)
++#define HSDMA_GLO_TX_DONE BIT(6)
++#define HSDMA_GLO_BT_MASK 0x3
++#define HSDMA_GLO_BT_SHIFT 4
++#define HSDMA_GLO_RX_BUSY BIT(3)
++#define HSDMA_GLO_RX_DMA BIT(2)
++#define HSDMA_GLO_TX_BUSY BIT(1)
++#define HSDMA_GLO_TX_DMA BIT(0)
++
++#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT)
++#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT)
++#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT)
++#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT)
++
++#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \
++ HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES)
++
++/* HSDMA_REG_RST_CFG */
++#define HSDMA_RST_RX_SHIFT 16
++#define HSDMA_RST_TX_SHIFT 0
++
++/* HSDMA_REG_DELAY_INT */
++#define HSDMA_DELAY_INT_EN BIT(15)
++#define HSDMA_DELAY_PEND_OFFSET 8
++#define HSDMA_DELAY_TIME_OFFSET 0
++#define HSDMA_DELAY_TX_OFFSET 16
++#define HSDMA_DELAY_RX_OFFSET 0
++
++#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \
++ ((x) << HSDMA_DELAY_PEND_OFFSET))
++#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \
++ HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x))
++
++/* HSDMA_REG_INT_STATUS */
++#define HSDMA_INT_DELAY_RX_COH BIT(31)
++#define HSDMA_INT_DELAY_RX_INT BIT(30)
++#define HSDMA_INT_DELAY_TX_COH BIT(29)
++#define HSDMA_INT_DELAY_TX_INT BIT(28)
++#define HSDMA_INT_RX_MASK 0x3
++#define HSDMA_INT_RX_SHIFT 16
++#define HSDMA_INT_RX_Q0 BIT(16)
++#define HSDMA_INT_TX_MASK 0xf
++#define HSDMA_INT_TX_SHIFT 0
++#define HSDMA_INT_TX_Q0 BIT(0)
++
++/* tx/rx dma desc flags */
++#define HSDMA_PLEN_MASK 0x3fff
++#define HSDMA_DESC_DONE BIT(31)
++#define HSDMA_DESC_LS0 BIT(30)
++#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16)
++#define HSDMA_DESC_TAG BIT(15)
++#define HSDMA_DESC_LS1 BIT(14)
++#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK)
++
++/* align 4 bytes */
++#define HSDMA_ALIGN_SIZE 3
++/* align size 128bytes */
++#define HSDMA_MAX_PLEN 0x3f80
++
++struct hsdma_desc {
++ u32 addr0;
++ u32 flags;
++ u32 addr1;
++ u32 unused;
++};
++
++struct mtk_hsdma_sg {
++ dma_addr_t src_addr;
++ dma_addr_t dst_addr;
++ u32 len;
++};
++
++struct mtk_hsdma_desc {
++ struct virt_dma_desc vdesc;
++ unsigned int num_sgs;
++ struct mtk_hsdma_sg sg[1];
++};
++
++struct mtk_hsdma_chan {
++ struct virt_dma_chan vchan;
++ unsigned int id;
++ dma_addr_t desc_addr;
++ int tx_idx;
++ int rx_idx;
++ struct hsdma_desc *tx_ring;
++ struct hsdma_desc *rx_ring;
++ struct mtk_hsdma_desc *desc;
++ unsigned int next_sg;
++};
++
++struct mtk_hsdam_engine {
++ struct dma_device ddev;
++ struct device_dma_parameters dma_parms;
++ void __iomem *base;
++ struct tasklet_struct task;
++ volatile unsigned long chan_issued;
++
++ struct mtk_hsdma_chan chan[1];
++};
++
++static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev(
++ struct mtk_hsdma_chan *chan)
++{
++ return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine,
++ ddev);
++}
++
++static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c)
++{
++ return container_of(c, struct mtk_hsdma_chan, vchan.chan);
++}
++
++static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc(
++ struct virt_dma_desc *vdesc)
++{
++ return container_of(vdesc, struct mtk_hsdma_desc, vdesc);
++}
++
++static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg)
++{
++ return readl(hsdma->base + reg);
++}
++
++static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma,
++ unsigned int reg, u32 val)
++{
++ writel(val, hsdma->base + reg);
++}
++
++static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ chan->tx_idx = 0;
++ chan->rx_idx = HSDMA_DESCS_NUM - 1;
++
++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx);
++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx);
++
++ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG,
++ 0x1 << (chan->id + HSDMA_RST_TX_SHIFT));
++ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG,
++ 0x1 << (chan->id + HSDMA_RST_RX_SHIFT));
++}
++
++static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma)
++{
++ dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, " \
++ "tctx %08x, tdtx: %08x, rbase %08x, " \
++ "rcnt %08x, rctx %08x, rdtx %08x\n",
++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE),
++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT),
++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX),
++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX),
++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE),
++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT),
++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX),
++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX));
++
++ dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, " \
++ "intr_stat %08x, intr_mask %08x\n",
++ mtk_hsdma_read(hsdma, HSDMA_REG_INFO),
++ mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG),
++ mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT),
++ mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS),
++ mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK));
++}
++
++static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ struct hsdma_desc *tx_desc;
++ struct hsdma_desc *rx_desc;
++ int i;
++
++ dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n",
++ chan->tx_idx, chan->rx_idx);
++
++ for (i = 0; i < HSDMA_DESCS_NUM; i++) {
++ tx_desc = &chan->tx_ring[i];
++ rx_desc = &chan->rx_ring[i];
++
++ dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, " \
++ "tx addr1: %08x, rx addr0 %08x, flags %08x\n",
++ i, tx_desc->addr0, tx_desc->flags, \
++ tx_desc->addr1, rx_desc->addr0, rx_desc->flags);
++ }
++}
++
++static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ int i;
++
++ /* disable dma */
++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0);
++
++ /* disable intr */
++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0);
++
++ /* init desc value */
++ for (i = 0; i < HSDMA_DESCS_NUM; i++) {
++ chan->tx_ring[i].addr0 = 0;
++ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE;
++ }
++ for (i = 0; i < HSDMA_DESCS_NUM; i++) {
++ chan->rx_ring[i].addr0 = 0;
++ chan->rx_ring[i].flags = 0;
++ }
++
++ /* reset */
++ mtk_hsdma_reset_chan(hsdma, chan);
++
++ /* enable intr */
++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0);
++
++ /* enable dma */
++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT);
++}
++
++static int mtk_hsdma_terminate_all(struct dma_chan *c)
++{
++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
++ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan);
++ unsigned long timeout;
++ LIST_HEAD(head);
++
++ spin_lock_bh(&chan->vchan.lock);
++ chan->desc = NULL;
++ clear_bit(chan->id, &hsdma->chan_issued);
++ vchan_get_all_descriptors(&chan->vchan, &head);
++ spin_unlock_bh(&chan->vchan.lock);
++
++ vchan_dma_desc_free_list(&chan->vchan, &head);
++
++ /* wait dma transfer complete */
++ timeout = jiffies + msecs_to_jiffies(2000);
++ while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) &
++ (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) {
++ if (time_after_eq(jiffies, timeout)) {
++ hsdma_dump_desc(hsdma, chan);
++ mtk_hsdma_reset(hsdma, chan);
++ dev_err(hsdma->ddev.dev, "timeout, reset it\n");
++ break;
++ }
++ cpu_relax();
++ }
++
++ return 0;
++}
++
++static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ dma_addr_t src, dst;
++ size_t len, tlen;
++ struct hsdma_desc *tx_desc, *rx_desc;
++ struct mtk_hsdma_sg *sg;
++ unsigned int i;
++ int rx_idx;
++
++ sg = &chan->desc->sg[0];
++ len = sg->len;
++ chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN);
++
++ /* tx desc */
++ src = sg->src_addr;
++ for (i = 0; i < chan->desc->num_sgs; i++) {
++ tx_desc = &chan->tx_ring[chan->tx_idx];
++
++ if (len > HSDMA_MAX_PLEN)
++ tlen = HSDMA_MAX_PLEN;
++ else
++ tlen = len;
++
++ if (i & 0x1) {
++ tx_desc->addr1 = src;
++ tx_desc->flags |= HSDMA_DESC_PLEN1(tlen);
++ } else {
++ tx_desc->addr0 = src;
++ tx_desc->flags = HSDMA_DESC_PLEN0(tlen);
++
++ /* update index */
++ chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx);
++ }
++
++ src += tlen;
++ len -= tlen;
++ }
++ if (i & 0x1)
++ tx_desc->flags |= HSDMA_DESC_LS0;
++ else
++ tx_desc->flags |= HSDMA_DESC_LS1;
++
++ /* rx desc */
++ rx_idx = HSDMA_NEXT_DESC(chan->rx_idx);
++ len = sg->len;
++ dst = sg->dst_addr;
++ for (i = 0; i < chan->desc->num_sgs; i++) {
++ rx_desc = &chan->rx_ring[rx_idx];
++ if (len > HSDMA_MAX_PLEN)
++ tlen = HSDMA_MAX_PLEN;
++ else
++ tlen = len;
++
++ rx_desc->addr0 = dst;
++ rx_desc->flags = HSDMA_DESC_PLEN0(tlen);
++
++ dst += tlen;
++ len -= tlen;
++
++ /* update index */
++ rx_idx = HSDMA_NEXT_DESC(rx_idx);
++ }
++
++ /* make sure desc and index all up to date */
++ wmb();
++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx);
++
++ return 0;
++}
++
++static int gdma_next_desc(struct mtk_hsdma_chan *chan)
++{
++ struct virt_dma_desc *vdesc;
++
++ vdesc = vchan_next_desc(&chan->vchan);
++ if (!vdesc) {
++ chan->desc = NULL;
++ return 0;
++ }
++ chan->desc = to_mtk_hsdma_desc(vdesc);
++ chan->next_sg = 0;
++
++ return 1;
++}
++
++static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ struct mtk_hsdma_desc *desc;
++ int chan_issued;
++
++ chan_issued = 0;
++ spin_lock_bh(&chan->vchan.lock);
++ desc = chan->desc;
++ if (likely(desc)) {
++ if (chan->next_sg == desc->num_sgs) {
++ list_del(&desc->vdesc.node);
++ vchan_cookie_complete(&desc->vdesc);
++ chan_issued = gdma_next_desc(chan);
++ }
++ } else {
++ dev_dbg(hsdma->ddev.dev, "no desc to complete\n");
++ }
++
++ if (chan_issued)
++ set_bit(chan->id, &hsdma->chan_issued);
++ spin_unlock_bh(&chan->vchan.lock);
++}
++
++static irqreturn_t mtk_hsdma_irq(int irq, void *devid)
++{
++ struct mtk_hsdam_engine *hsdma = devid;
++ u32 status;
++
++ status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS);
++ if (unlikely(!status))
++ return IRQ_NONE;
++
++ if (likely(status & HSDMA_INT_RX_Q0))
++ tasklet_schedule(&hsdma->task);
++ else
++ dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", status);
++ /* clean intr bits */
++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status);
++
++ return IRQ_HANDLED;
++}
++
++static void mtk_hsdma_issue_pending(struct dma_chan *c)
++{
++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
++ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan);
++
++ spin_lock_bh(&chan->vchan.lock);
++ if (vchan_issue_pending(&chan->vchan) && !chan->desc) {
++ if (gdma_next_desc(chan)) {
++ set_bit(chan->id, &hsdma->chan_issued);
++ tasklet_schedule(&hsdma->task);
++ } else {
++ dev_dbg(hsdma->ddev.dev, "no desc to issue\n");
++ }
++ }
++ spin_unlock_bh(&chan->vchan.lock);
++}
++
++static struct dma_async_tx_descriptor *mtk_hsdma_prep_dma_memcpy(
++ struct dma_chan *c, dma_addr_t dest, dma_addr_t src,
++ size_t len, unsigned long flags)
++{
++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
++ struct mtk_hsdma_desc *desc;
++
++ if (len <= 0)
++ return NULL;
++
++ desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
++ if (!desc) {
++ dev_err(c->device->dev, "alloc memcpy decs error\n");
++ return NULL;
++ }
++
++ desc->sg[0].src_addr = src;
++ desc->sg[0].dst_addr = dest;
++ desc->sg[0].len = len;
++
++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
++}
++
++static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c,
++ dma_cookie_t cookie,
++ struct dma_tx_state *state)
++{
++ return dma_cookie_status(c, cookie, state);
++}
++
++static void mtk_hsdma_free_chan_resources(struct dma_chan *c)
++{
++ vchan_free_chan_resources(to_virt_chan(c));
++}
++
++static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc)
++{
++ kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc));
++}
++
++static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma)
++{
++ struct mtk_hsdma_chan *chan;
++
++ if (test_and_clear_bit(0, &hsdma->chan_issued)) {
++ chan = &hsdma->chan[0];
++ if (chan->desc)
++ mtk_hsdma_start_transfer(hsdma, chan);
++ else
++ dev_dbg(hsdma->ddev.dev, "chan 0 no desc to issue\n");
++ }
++}
++
++static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma)
++{
++ struct mtk_hsdma_chan *chan;
++ int next_idx, drx_idx, cnt;
++
++ chan = &hsdma->chan[0];
++ next_idx = HSDMA_NEXT_DESC(chan->rx_idx);
++ drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX);
++
++ cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK;
++ if (!cnt)
++ return;
++
++ chan->next_sg += cnt;
++ chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK;
++
++ /* update rx crx */
++ wmb();
++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx);
++
++ mtk_hsdma_chan_done(hsdma, chan);
++}
++
++static void mtk_hsdma_tasklet(unsigned long arg)
++{
++ struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg;
++
++ mtk_hsdma_rx(hsdma);
++ mtk_hsdma_tx(hsdma);
++}
++
++static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ int i;
++
++ chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev,
++ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
++ &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO);
++ if (!chan->tx_ring)
++ goto no_mem;
++
++ chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM];
++
++ /* init tx ring value */
++ for (i = 0; i < HSDMA_DESCS_NUM; i++)
++ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE;
++
++ return 0;
++no_mem:
++ return -ENOMEM;
++}
++
++static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma,
++ struct mtk_hsdma_chan *chan)
++{
++ if (chan->tx_ring) {
++ dma_free_coherent(hsdma->ddev.dev,
++ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
++ chan->tx_ring, chan->desc_addr);
++ chan->tx_ring = NULL;
++ chan->rx_ring = NULL;
++ }
++}
++
++static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma)
++{
++ struct mtk_hsdma_chan *chan;
++ int ret;
++ u32 reg;
++
++ /* init desc */
++ chan = &hsdma->chan[0];
++ ret = mtk_hsdam_alloc_desc(hsdma, chan);
++ if (ret)
++ return ret;
++
++ /* tx */
++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr);
++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM);
++ /* rx */
++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr +
++ (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM));
++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM);
++ /* reset */
++ mtk_hsdma_reset_chan(hsdma, chan);
++
++ /* enable rx intr */
++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0);
++
++ /* enable dma */
++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT);
++
++ /* hardware info */
++ reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO);
++ dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n",
++ (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK,
++ (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK);
++
++ hsdma_dump_reg(hsdma);
++
++ return ret;
++}
++
++static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma)
++{
++ struct mtk_hsdma_chan *chan;
++
++ /* disable dma */
++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0);
++
++ /* disable intr */
++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0);
++
++ /* free desc */
++ chan = &hsdma->chan[0];
++ mtk_hsdam_free_desc(hsdma, chan);
++
++ /* tx */
++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0);
++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0);
++ /* rx */
++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0);
++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0);
++ /* reset */
++ mtk_hsdma_reset_chan(hsdma, chan);
++}
++
++static const struct of_device_id mtk_hsdma_of_match[] = {
++ { .compatible = "mediatek,mt7621-hsdma" },
++ { },
++};
++
++static int mtk_hsdma_probe(struct platform_device *pdev)
++{
++ const struct of_device_id *match;
++ struct mtk_hsdma_chan *chan;
++ struct mtk_hsdam_engine *hsdma;
++ struct dma_device *dd;
++ struct resource *res;
++ int ret;
++ int irq;
++ void __iomem *base;
++
++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
++ if (ret)
++ return ret;
++
++ match = of_match_device(mtk_hsdma_of_match, &pdev->dev);
++ if (!match)
++ return -EINVAL;
++
++ hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL);
++ if (!hsdma)
++ return -EINVAL;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++ hsdma->base = base + HSDMA_BASE_OFFSET;
++ tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma);
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0)
++ return -EINVAL;
++ ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq,
++ 0, dev_name(&pdev->dev), hsdma);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to request irq\n");
++ return ret;
++ }
++
++ device_reset(&pdev->dev);
++
++ dd = &hsdma->ddev;
++ dma_cap_set(DMA_MEMCPY, dd->cap_mask);
++ dd->copy_align = HSDMA_ALIGN_SIZE;
++ dd->device_free_chan_resources = mtk_hsdma_free_chan_resources;
++ dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy;
++ dd->device_terminate_all = mtk_hsdma_terminate_all;
++ dd->device_tx_status = mtk_hsdma_tx_status;
++ dd->device_issue_pending = mtk_hsdma_issue_pending;
++ dd->dev = &pdev->dev;
++ dd->dev->dma_parms = &hsdma->dma_parms;
++ dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN);
++ INIT_LIST_HEAD(&dd->channels);
++
++ chan = &hsdma->chan[0];
++ chan->id = 0;
++ chan->vchan.desc_free = mtk_hsdma_desc_free;
++ vchan_init(&chan->vchan, dd);
++
++ /* init hardware */
++ ret = mtk_hsdma_init(hsdma);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to alloc ring descs\n");
++ return ret;
++ }
++
++ ret = dma_async_device_register(dd);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to register dma device\n");
++ goto err_uninit_hsdma;
++ }
++
++ ret = of_dma_controller_register(pdev->dev.of_node,
++ of_dma_xlate_by_chan_id, hsdma);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to register of dma controller\n");
++ goto err_unregister;
++ }
++
++ platform_set_drvdata(pdev, hsdma);
++
++ return 0;
++
++err_unregister:
++ dma_async_device_unregister(dd);
++err_uninit_hsdma:
++ mtk_hsdma_uninit(hsdma);
++ return ret;
++}
++
++static int mtk_hsdma_remove(struct platform_device *pdev)
++{
++ struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev);
++
++ mtk_hsdma_uninit(hsdma);
++
++ of_dma_controller_free(pdev->dev.of_node);
++ dma_async_device_unregister(&hsdma->ddev);
++
++ return 0;
++}
++
++static struct platform_driver mtk_hsdma_driver = {
++ .probe = mtk_hsdma_probe,
++ .remove = mtk_hsdma_remove,
++ .driver = {
++ .name = KBUILD_MODNAME,
++ .of_match_table = mtk_hsdma_of_match,
++ },
++};
++module_platform_driver(mtk_hsdma_driver);
++
++MODULE_AUTHOR("Michael Lee <igvtee@gmail.com>");
++MODULE_DESCRIPTION("MTK HSDMA driver");
++MODULE_LICENSE("GPL v2");
+--- a/drivers/staging/mt7621-dma/mtk-hsdma.c
++++ /dev/null
+@@ -1,762 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0+
+-/*
+- * Copyright (C) 2015, Michael Lee <igvtee@gmail.com>
+- * MTK HSDMA support
+- */
+-
+-#include <linux/dmaengine.h>
+-#include <linux/dma-mapping.h>
+-#include <linux/err.h>
+-#include <linux/init.h>
+-#include <linux/list.h>
+-#include <linux/module.h>
+-#include <linux/platform_device.h>
+-#include <linux/slab.h>
+-#include <linux/spinlock.h>
+-#include <linux/irq.h>
+-#include <linux/of_dma.h>
+-#include <linux/reset.h>
+-#include <linux/of_device.h>
+-
+-#include "virt-dma.h"
+-
+-#define HSDMA_BASE_OFFSET 0x800
+-
+-#define HSDMA_REG_TX_BASE 0x00
+-#define HSDMA_REG_TX_CNT 0x04
+-#define HSDMA_REG_TX_CTX 0x08
+-#define HSDMA_REG_TX_DTX 0x0c
+-#define HSDMA_REG_RX_BASE 0x100
+-#define HSDMA_REG_RX_CNT 0x104
+-#define HSDMA_REG_RX_CRX 0x108
+-#define HSDMA_REG_RX_DRX 0x10c
+-#define HSDMA_REG_INFO 0x200
+-#define HSDMA_REG_GLO_CFG 0x204
+-#define HSDMA_REG_RST_CFG 0x208
+-#define HSDMA_REG_DELAY_INT 0x20c
+-#define HSDMA_REG_FREEQ_THRES 0x210
+-#define HSDMA_REG_INT_STATUS 0x220
+-#define HSDMA_REG_INT_MASK 0x228
+-#define HSDMA_REG_SCH_Q01 0x280
+-#define HSDMA_REG_SCH_Q23 0x284
+-
+-#define HSDMA_DESCS_MAX 0xfff
+-#define HSDMA_DESCS_NUM 8
+-#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1)
+-#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK)
+-
+-/* HSDMA_REG_INFO */
+-#define HSDMA_INFO_INDEX_MASK 0xf
+-#define HSDMA_INFO_INDEX_SHIFT 24
+-#define HSDMA_INFO_BASE_MASK 0xff
+-#define HSDMA_INFO_BASE_SHIFT 16
+-#define HSDMA_INFO_RX_MASK 0xff
+-#define HSDMA_INFO_RX_SHIFT 8
+-#define HSDMA_INFO_TX_MASK 0xff
+-#define HSDMA_INFO_TX_SHIFT 0
+-
+-/* HSDMA_REG_GLO_CFG */
+-#define HSDMA_GLO_TX_2B_OFFSET BIT(31)
+-#define HSDMA_GLO_CLK_GATE BIT(30)
+-#define HSDMA_GLO_BYTE_SWAP BIT(29)
+-#define HSDMA_GLO_MULTI_DMA BIT(10)
+-#define HSDMA_GLO_TWO_BUF BIT(9)
+-#define HSDMA_GLO_32B_DESC BIT(8)
+-#define HSDMA_GLO_BIG_ENDIAN BIT(7)
+-#define HSDMA_GLO_TX_DONE BIT(6)
+-#define HSDMA_GLO_BT_MASK 0x3
+-#define HSDMA_GLO_BT_SHIFT 4
+-#define HSDMA_GLO_RX_BUSY BIT(3)
+-#define HSDMA_GLO_RX_DMA BIT(2)
+-#define HSDMA_GLO_TX_BUSY BIT(1)
+-#define HSDMA_GLO_TX_DMA BIT(0)
+-
+-#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT)
+-#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT)
+-#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT)
+-#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT)
+-
+-#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \
+- HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES)
+-
+-/* HSDMA_REG_RST_CFG */
+-#define HSDMA_RST_RX_SHIFT 16
+-#define HSDMA_RST_TX_SHIFT 0
+-
+-/* HSDMA_REG_DELAY_INT */
+-#define HSDMA_DELAY_INT_EN BIT(15)
+-#define HSDMA_DELAY_PEND_OFFSET 8
+-#define HSDMA_DELAY_TIME_OFFSET 0
+-#define HSDMA_DELAY_TX_OFFSET 16
+-#define HSDMA_DELAY_RX_OFFSET 0
+-
+-#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \
+- ((x) << HSDMA_DELAY_PEND_OFFSET))
+-#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \
+- HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x))
+-
+-/* HSDMA_REG_INT_STATUS */
+-#define HSDMA_INT_DELAY_RX_COH BIT(31)
+-#define HSDMA_INT_DELAY_RX_INT BIT(30)
+-#define HSDMA_INT_DELAY_TX_COH BIT(29)
+-#define HSDMA_INT_DELAY_TX_INT BIT(28)
+-#define HSDMA_INT_RX_MASK 0x3
+-#define HSDMA_INT_RX_SHIFT 16
+-#define HSDMA_INT_RX_Q0 BIT(16)
+-#define HSDMA_INT_TX_MASK 0xf
+-#define HSDMA_INT_TX_SHIFT 0
+-#define HSDMA_INT_TX_Q0 BIT(0)
+-
+-/* tx/rx dma desc flags */
+-#define HSDMA_PLEN_MASK 0x3fff
+-#define HSDMA_DESC_DONE BIT(31)
+-#define HSDMA_DESC_LS0 BIT(30)
+-#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16)
+-#define HSDMA_DESC_TAG BIT(15)
+-#define HSDMA_DESC_LS1 BIT(14)
+-#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK)
+-
+-/* align 4 bytes */
+-#define HSDMA_ALIGN_SIZE 3
+-/* align size 128bytes */
+-#define HSDMA_MAX_PLEN 0x3f80
+-
+-struct hsdma_desc {
+- u32 addr0;
+- u32 flags;
+- u32 addr1;
+- u32 unused;
+-};
+-
+-struct mtk_hsdma_sg {
+- dma_addr_t src_addr;
+- dma_addr_t dst_addr;
+- u32 len;
+-};
+-
+-struct mtk_hsdma_desc {
+- struct virt_dma_desc vdesc;
+- unsigned int num_sgs;
+- struct mtk_hsdma_sg sg[1];
+-};
+-
+-struct mtk_hsdma_chan {
+- struct virt_dma_chan vchan;
+- unsigned int id;
+- dma_addr_t desc_addr;
+- int tx_idx;
+- int rx_idx;
+- struct hsdma_desc *tx_ring;
+- struct hsdma_desc *rx_ring;
+- struct mtk_hsdma_desc *desc;
+- unsigned int next_sg;
+-};
+-
+-struct mtk_hsdam_engine {
+- struct dma_device ddev;
+- struct device_dma_parameters dma_parms;
+- void __iomem *base;
+- struct tasklet_struct task;
+- volatile unsigned long chan_issued;
+-
+- struct mtk_hsdma_chan chan[1];
+-};
+-
+-static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev(
+- struct mtk_hsdma_chan *chan)
+-{
+- return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine,
+- ddev);
+-}
+-
+-static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c)
+-{
+- return container_of(c, struct mtk_hsdma_chan, vchan.chan);
+-}
+-
+-static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc(
+- struct virt_dma_desc *vdesc)
+-{
+- return container_of(vdesc, struct mtk_hsdma_desc, vdesc);
+-}
+-
+-static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg)
+-{
+- return readl(hsdma->base + reg);
+-}
+-
+-static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma,
+- unsigned int reg, u32 val)
+-{
+- writel(val, hsdma->base + reg);
+-}
+-
+-static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- chan->tx_idx = 0;
+- chan->rx_idx = HSDMA_DESCS_NUM - 1;
+-
+- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx);
+- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx);
+-
+- mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG,
+- 0x1 << (chan->id + HSDMA_RST_TX_SHIFT));
+- mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG,
+- 0x1 << (chan->id + HSDMA_RST_RX_SHIFT));
+-}
+-
+-static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma)
+-{
+- dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, " \
+- "tctx %08x, tdtx: %08x, rbase %08x, " \
+- "rcnt %08x, rctx %08x, rdtx %08x\n",
+- mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE),
+- mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT),
+- mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX),
+- mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX),
+- mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE),
+- mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT),
+- mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX),
+- mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX));
+-
+- dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, " \
+- "intr_stat %08x, intr_mask %08x\n",
+- mtk_hsdma_read(hsdma, HSDMA_REG_INFO),
+- mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG),
+- mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT),
+- mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS),
+- mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK));
+-}
+-
+-static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- struct hsdma_desc *tx_desc;
+- struct hsdma_desc *rx_desc;
+- int i;
+-
+- dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n",
+- chan->tx_idx, chan->rx_idx);
+-
+- for (i = 0; i < HSDMA_DESCS_NUM; i++) {
+- tx_desc = &chan->tx_ring[i];
+- rx_desc = &chan->rx_ring[i];
+-
+- dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, " \
+- "tx addr1: %08x, rx addr0 %08x, flags %08x\n",
+- i, tx_desc->addr0, tx_desc->flags, \
+- tx_desc->addr1, rx_desc->addr0, rx_desc->flags);
+- }
+-}
+-
+-static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- int i;
+-
+- /* disable dma */
+- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0);
+-
+- /* disable intr */
+- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0);
+-
+- /* init desc value */
+- for (i = 0; i < HSDMA_DESCS_NUM; i++) {
+- chan->tx_ring[i].addr0 = 0;
+- chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE;
+- }
+- for (i = 0; i < HSDMA_DESCS_NUM; i++) {
+- chan->rx_ring[i].addr0 = 0;
+- chan->rx_ring[i].flags = 0;
+- }
+-
+- /* reset */
+- mtk_hsdma_reset_chan(hsdma, chan);
+-
+- /* enable intr */
+- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0);
+-
+- /* enable dma */
+- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT);
+-}
+-
+-static int mtk_hsdma_terminate_all(struct dma_chan *c)
+-{
+- struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
+- struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan);
+- unsigned long timeout;
+- LIST_HEAD(head);
+-
+- spin_lock_bh(&chan->vchan.lock);
+- chan->desc = NULL;
+- clear_bit(chan->id, &hsdma->chan_issued);
+- vchan_get_all_descriptors(&chan->vchan, &head);
+- spin_unlock_bh(&chan->vchan.lock);
+-
+- vchan_dma_desc_free_list(&chan->vchan, &head);
+-
+- /* wait dma transfer complete */
+- timeout = jiffies + msecs_to_jiffies(2000);
+- while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) &
+- (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) {
+- if (time_after_eq(jiffies, timeout)) {
+- hsdma_dump_desc(hsdma, chan);
+- mtk_hsdma_reset(hsdma, chan);
+- dev_err(hsdma->ddev.dev, "timeout, reset it\n");
+- break;
+- }
+- cpu_relax();
+- }
+-
+- return 0;
+-}
+-
+-static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- dma_addr_t src, dst;
+- size_t len, tlen;
+- struct hsdma_desc *tx_desc, *rx_desc;
+- struct mtk_hsdma_sg *sg;
+- unsigned int i;
+- int rx_idx;
+-
+- sg = &chan->desc->sg[0];
+- len = sg->len;
+- chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN);
+-
+- /* tx desc */
+- src = sg->src_addr;
+- for (i = 0; i < chan->desc->num_sgs; i++) {
+- tx_desc = &chan->tx_ring[chan->tx_idx];
+-
+- if (len > HSDMA_MAX_PLEN)
+- tlen = HSDMA_MAX_PLEN;
+- else
+- tlen = len;
+-
+- if (i & 0x1) {
+- tx_desc->addr1 = src;
+- tx_desc->flags |= HSDMA_DESC_PLEN1(tlen);
+- } else {
+- tx_desc->addr0 = src;
+- tx_desc->flags = HSDMA_DESC_PLEN0(tlen);
+-
+- /* update index */
+- chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx);
+- }
+-
+- src += tlen;
+- len -= tlen;
+- }
+- if (i & 0x1)
+- tx_desc->flags |= HSDMA_DESC_LS0;
+- else
+- tx_desc->flags |= HSDMA_DESC_LS1;
+-
+- /* rx desc */
+- rx_idx = HSDMA_NEXT_DESC(chan->rx_idx);
+- len = sg->len;
+- dst = sg->dst_addr;
+- for (i = 0; i < chan->desc->num_sgs; i++) {
+- rx_desc = &chan->rx_ring[rx_idx];
+- if (len > HSDMA_MAX_PLEN)
+- tlen = HSDMA_MAX_PLEN;
+- else
+- tlen = len;
+-
+- rx_desc->addr0 = dst;
+- rx_desc->flags = HSDMA_DESC_PLEN0(tlen);
+-
+- dst += tlen;
+- len -= tlen;
+-
+- /* update index */
+- rx_idx = HSDMA_NEXT_DESC(rx_idx);
+- }
+-
+- /* make sure desc and index all up to date */
+- wmb();
+- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx);
+-
+- return 0;
+-}
+-
+-static int gdma_next_desc(struct mtk_hsdma_chan *chan)
+-{
+- struct virt_dma_desc *vdesc;
+-
+- vdesc = vchan_next_desc(&chan->vchan);
+- if (!vdesc) {
+- chan->desc = NULL;
+- return 0;
+- }
+- chan->desc = to_mtk_hsdma_desc(vdesc);
+- chan->next_sg = 0;
+-
+- return 1;
+-}
+-
+-static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- struct mtk_hsdma_desc *desc;
+- int chan_issued;
+-
+- chan_issued = 0;
+- spin_lock_bh(&chan->vchan.lock);
+- desc = chan->desc;
+- if (likely(desc)) {
+- if (chan->next_sg == desc->num_sgs) {
+- list_del(&desc->vdesc.node);
+- vchan_cookie_complete(&desc->vdesc);
+- chan_issued = gdma_next_desc(chan);
+- }
+- } else {
+- dev_dbg(hsdma->ddev.dev, "no desc to complete\n");
+- }
+-
+- if (chan_issued)
+- set_bit(chan->id, &hsdma->chan_issued);
+- spin_unlock_bh(&chan->vchan.lock);
+-}
+-
+-static irqreturn_t mtk_hsdma_irq(int irq, void *devid)
+-{
+- struct mtk_hsdam_engine *hsdma = devid;
+- u32 status;
+-
+- status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS);
+- if (unlikely(!status))
+- return IRQ_NONE;
+-
+- if (likely(status & HSDMA_INT_RX_Q0))
+- tasklet_schedule(&hsdma->task);
+- else
+- dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", status);
+- /* clean intr bits */
+- mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status);
+-
+- return IRQ_HANDLED;
+-}
+-
+-static void mtk_hsdma_issue_pending(struct dma_chan *c)
+-{
+- struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
+- struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan);
+-
+- spin_lock_bh(&chan->vchan.lock);
+- if (vchan_issue_pending(&chan->vchan) && !chan->desc) {
+- if (gdma_next_desc(chan)) {
+- set_bit(chan->id, &hsdma->chan_issued);
+- tasklet_schedule(&hsdma->task);
+- } else {
+- dev_dbg(hsdma->ddev.dev, "no desc to issue\n");
+- }
+- }
+- spin_unlock_bh(&chan->vchan.lock);
+-}
+-
+-static struct dma_async_tx_descriptor *mtk_hsdma_prep_dma_memcpy(
+- struct dma_chan *c, dma_addr_t dest, dma_addr_t src,
+- size_t len, unsigned long flags)
+-{
+- struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c);
+- struct mtk_hsdma_desc *desc;
+-
+- if (len <= 0)
+- return NULL;
+-
+- desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
+- if (!desc) {
+- dev_err(c->device->dev, "alloc memcpy decs error\n");
+- return NULL;
+- }
+-
+- desc->sg[0].src_addr = src;
+- desc->sg[0].dst_addr = dest;
+- desc->sg[0].len = len;
+-
+- return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
+-}
+-
+-static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c,
+- dma_cookie_t cookie,
+- struct dma_tx_state *state)
+-{
+- return dma_cookie_status(c, cookie, state);
+-}
+-
+-static void mtk_hsdma_free_chan_resources(struct dma_chan *c)
+-{
+- vchan_free_chan_resources(to_virt_chan(c));
+-}
+-
+-static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc)
+-{
+- kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc));
+-}
+-
+-static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma)
+-{
+- struct mtk_hsdma_chan *chan;
+-
+- if (test_and_clear_bit(0, &hsdma->chan_issued)) {
+- chan = &hsdma->chan[0];
+- if (chan->desc)
+- mtk_hsdma_start_transfer(hsdma, chan);
+- else
+- dev_dbg(hsdma->ddev.dev, "chan 0 no desc to issue\n");
+- }
+-}
+-
+-static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma)
+-{
+- struct mtk_hsdma_chan *chan;
+- int next_idx, drx_idx, cnt;
+-
+- chan = &hsdma->chan[0];
+- next_idx = HSDMA_NEXT_DESC(chan->rx_idx);
+- drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX);
+-
+- cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK;
+- if (!cnt)
+- return;
+-
+- chan->next_sg += cnt;
+- chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK;
+-
+- /* update rx crx */
+- wmb();
+- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx);
+-
+- mtk_hsdma_chan_done(hsdma, chan);
+-}
+-
+-static void mtk_hsdma_tasklet(unsigned long arg)
+-{
+- struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg;
+-
+- mtk_hsdma_rx(hsdma);
+- mtk_hsdma_tx(hsdma);
+-}
+-
+-static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- int i;
+-
+- chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev,
+- 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
+- &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO);
+- if (!chan->tx_ring)
+- goto no_mem;
+-
+- chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM];
+-
+- /* init tx ring value */
+- for (i = 0; i < HSDMA_DESCS_NUM; i++)
+- chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE;
+-
+- return 0;
+-no_mem:
+- return -ENOMEM;
+-}
+-
+-static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma,
+- struct mtk_hsdma_chan *chan)
+-{
+- if (chan->tx_ring) {
+- dma_free_coherent(hsdma->ddev.dev,
+- 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring),
+- chan->tx_ring, chan->desc_addr);
+- chan->tx_ring = NULL;
+- chan->rx_ring = NULL;
+- }
+-}
+-
+-static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma)
+-{
+- struct mtk_hsdma_chan *chan;
+- int ret;
+- u32 reg;
+-
+- /* init desc */
+- chan = &hsdma->chan[0];
+- ret = mtk_hsdam_alloc_desc(hsdma, chan);
+- if (ret)
+- return ret;
+-
+- /* tx */
+- mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr);
+- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM);
+- /* rx */
+- mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr +
+- (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM));
+- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM);
+- /* reset */
+- mtk_hsdma_reset_chan(hsdma, chan);
+-
+- /* enable rx intr */
+- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0);
+-
+- /* enable dma */
+- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT);
+-
+- /* hardware info */
+- reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO);
+- dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n",
+- (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK,
+- (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK);
+-
+- hsdma_dump_reg(hsdma);
+-
+- return ret;
+-}
+-
+-static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma)
+-{
+- struct mtk_hsdma_chan *chan;
+-
+- /* disable dma */
+- mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0);
+-
+- /* disable intr */
+- mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0);
+-
+- /* free desc */
+- chan = &hsdma->chan[0];
+- mtk_hsdam_free_desc(hsdma, chan);
+-
+- /* tx */
+- mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0);
+- mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0);
+- /* rx */
+- mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0);
+- mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0);
+- /* reset */
+- mtk_hsdma_reset_chan(hsdma, chan);
+-}
+-
+-static const struct of_device_id mtk_hsdma_of_match[] = {
+- { .compatible = "mediatek,mt7621-hsdma" },
+- { },
+-};
+-
+-static int mtk_hsdma_probe(struct platform_device *pdev)
+-{
+- const struct of_device_id *match;
+- struct mtk_hsdma_chan *chan;
+- struct mtk_hsdam_engine *hsdma;
+- struct dma_device *dd;
+- struct resource *res;
+- int ret;
+- int irq;
+- void __iomem *base;
+-
+- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+- if (ret)
+- return ret;
+-
+- match = of_match_device(mtk_hsdma_of_match, &pdev->dev);
+- if (!match)
+- return -EINVAL;
+-
+- hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL);
+- if (!hsdma)
+- return -EINVAL;
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- base = devm_ioremap_resource(&pdev->dev, res);
+- if (IS_ERR(base))
+- return PTR_ERR(base);
+- hsdma->base = base + HSDMA_BASE_OFFSET;
+- tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma);
+-
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0)
+- return -EINVAL;
+- ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq,
+- 0, dev_name(&pdev->dev), hsdma);
+- if (ret) {
+- dev_err(&pdev->dev, "failed to request irq\n");
+- return ret;
+- }
+-
+- device_reset(&pdev->dev);
+-
+- dd = &hsdma->ddev;
+- dma_cap_set(DMA_MEMCPY, dd->cap_mask);
+- dd->copy_align = HSDMA_ALIGN_SIZE;
+- dd->device_free_chan_resources = mtk_hsdma_free_chan_resources;
+- dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy;
+- dd->device_terminate_all = mtk_hsdma_terminate_all;
+- dd->device_tx_status = mtk_hsdma_tx_status;
+- dd->device_issue_pending = mtk_hsdma_issue_pending;
+- dd->dev = &pdev->dev;
+- dd->dev->dma_parms = &hsdma->dma_parms;
+- dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN);
+- INIT_LIST_HEAD(&dd->channels);
+-
+- chan = &hsdma->chan[0];
+- chan->id = 0;
+- chan->vchan.desc_free = mtk_hsdma_desc_free;
+- vchan_init(&chan->vchan, dd);
+-
+- /* init hardware */
+- ret = mtk_hsdma_init(hsdma);
+- if (ret) {
+- dev_err(&pdev->dev, "failed to alloc ring descs\n");
+- return ret;
+- }
+-
+- ret = dma_async_device_register(dd);
+- if (ret) {
+- dev_err(&pdev->dev, "failed to register dma device\n");
+- goto err_uninit_hsdma;
+- }
+-
+- ret = of_dma_controller_register(pdev->dev.of_node,
+- of_dma_xlate_by_chan_id, hsdma);
+- if (ret) {
+- dev_err(&pdev->dev, "failed to register of dma controller\n");
+- goto err_unregister;
+- }
+-
+- platform_set_drvdata(pdev, hsdma);
+-
+- return 0;
+-
+-err_unregister:
+- dma_async_device_unregister(dd);
+-err_uninit_hsdma:
+- mtk_hsdma_uninit(hsdma);
+- return ret;
+-}
+-
+-static int mtk_hsdma_remove(struct platform_device *pdev)
+-{
+- struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev);
+-
+- mtk_hsdma_uninit(hsdma);
+-
+- of_dma_controller_free(pdev->dev.of_node);
+- dma_async_device_unregister(&hsdma->ddev);
+-
+- return 0;
+-}
+-
+-static struct platform_driver mtk_hsdma_driver = {
+- .probe = mtk_hsdma_probe,
+- .remove = mtk_hsdma_remove,
+- .driver = {
+- .name = "hsdma-mt7621",
+- .of_match_table = mtk_hsdma_of_match,
+- },
+-};
+-module_platform_driver(mtk_hsdma_driver);
+-
+-MODULE_AUTHOR("Michael Lee <igvtee@gmail.com>");
+-MODULE_DESCRIPTION("MTK HSDMA driver");
+-MODULE_LICENSE("GPL v2");
--- /dev/null
+From 7a8d2f1908a59003e55ef8691d09efb7fbc51625 Mon Sep 17 00:00:00 2001
+From: Martin Kaiser <martin@kaiser.cx>
+Date: Thu, 4 Feb 2021 09:52:17 +0100
+Subject: staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
+
+From: Martin Kaiser <martin@kaiser.cx>
+
+commit 7a8d2f1908a59003e55ef8691d09efb7fbc51625 upstream.
+
+The Edimax EW-7811UN V2 uses an RTL8188EU chipset and works with this
+driver.
+
+Signed-off-by: Martin Kaiser <martin@kaiser.cx>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210204085217.9743-1-martin@kaiser.cx
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/rtl8188eu/os_dep/usb_intf.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
++++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+@@ -41,6 +41,7 @@ static const struct usb_device_id rtw_us
+ {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
+ {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */
+ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
++ {USB_DEVICE(0x7392, 0xb811)}, /* Edimax EW-7811UN V2 */
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
+ {} /* Terminating entry */
+ };
--- /dev/null
+From e42acf104d6e0bd7ccd2f09103d5be5e6d3c637c Mon Sep 17 00:00:00 2001
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+Date: Thu, 1 Oct 2020 11:09:22 -0700
+Subject: tpm_tis: Clean up locality release
+
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+
+commit e42acf104d6e0bd7ccd2f09103d5be5e6d3c637c upstream.
+
+The current release locality code seems to be based on the
+misunderstanding that the TPM interrupts when a locality is released:
+it doesn't, only when the locality is acquired.
+
+Furthermore, there seems to be no point in waiting for the locality to
+be released. All it does is penalize the last TPM user. However, if
+there's no next TPM user, this is a pointless wait and if there is a
+next TPM user, they'll pay the penalty waiting for the new locality
+(or possibly not if it's the same as the old locality).
+
+Fix the code by making release_locality as simple write to release
+with no waiting for completion.
+
+Cc: stable@ger.kernel.org
+Fixes: 33bafe90824b ("tpm_tis: verify locality released before returning from release_locality")
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 47 ----------------------------------------
+ 1 file changed, 1 insertion(+), 46 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -135,58 +135,13 @@ static bool check_locality(struct tpm_ch
+ return false;
+ }
+
+-static bool locality_inactive(struct tpm_chip *chip, int l)
+-{
+- struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+- int rc;
+- u8 access;
+-
+- rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
+- if (rc < 0)
+- return false;
+-
+- if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
+- == TPM_ACCESS_VALID)
+- return true;
+-
+- return false;
+-}
+-
+ static int release_locality(struct tpm_chip *chip, int l)
+ {
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+- unsigned long stop, timeout;
+- long rc;
+
+ tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
+
+- stop = jiffies + chip->timeout_a;
+-
+- if (chip->flags & TPM_CHIP_FLAG_IRQ) {
+-again:
+- timeout = stop - jiffies;
+- if ((long)timeout <= 0)
+- return -1;
+-
+- rc = wait_event_interruptible_timeout(priv->int_queue,
+- (locality_inactive(chip, l)),
+- timeout);
+-
+- if (rc > 0)
+- return 0;
+-
+- if (rc == -ERESTARTSYS && freezing(current)) {
+- clear_thread_flag(TIF_SIGPENDING);
+- goto again;
+- }
+- } else {
+- do {
+- if (locality_inactive(chip, l))
+- return 0;
+- tpm_msleep(TPM_TIMEOUT);
+- } while (time_before(jiffies, stop));
+- }
+- return -1;
++ return 0;
+ }
+
+ static int request_locality(struct tpm_chip *chip, int l)
--- /dev/null
+From 3d9ae54af1d02a7c0edc55c77d7df2b921e58a87 Mon Sep 17 00:00:00 2001
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+Date: Thu, 1 Oct 2020 11:09:21 -0700
+Subject: tpm_tis: Fix check_locality for correct locality acquisition
+
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+
+commit 3d9ae54af1d02a7c0edc55c77d7df2b921e58a87 upstream.
+
+The TPM TIS specification says the TPM signals the acquisition of locality
+when the TMP_ACCESS_REQUEST_USE bit goes to one *and* the
+TPM_ACCESS_REQUEST_USE bit goes to zero. Currently we only check the
+former not the latter, so check both. Adding the check on
+TPM_ACCESS_REQUEST_USE should fix the case where the locality is
+re-requested before the TPM has released it. In this case the locality may
+get released briefly before it is reacquired, which causes all sorts of
+problems. However, with the added check, TPM_ACCESS_REQUEST_USE should
+remain 1 until the second request for the locality is granted.
+
+Cc: stable@ger.kernel.org
+Fixes: 27084efee0c3 ("[PATCH] tpm: driver for next generation TPM chips")
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -125,7 +125,8 @@ static bool check_locality(struct tpm_ch
+ if (rc < 0)
+ return false;
+
+- if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
++ if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID
++ | TPM_ACCESS_REQUEST_USE)) ==
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
+ priv->locality = l;
+ return true;
--- /dev/null
+From 4b049f55ed95cd889bcdb3034fd75e1f01852b38 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Mon, 8 Feb 2021 13:53:16 -0800
+Subject: usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit 4b049f55ed95cd889bcdb3034fd75e1f01852b38 upstream.
+
+The dep->interval captures the number of frames/microframes per interval
+from bInterval. Fullspeed interrupt endpoint bInterval is the number of
+frames per interval and not 2^(bInterval - 1). So fix it here. This
+change is only for debugging purpose and should not affect the interrupt
+endpoint operation.
+
+Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/1263b563dedc4ab8b0fb854fba06ce4bc56bd495.1612820995.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -603,8 +603,13 @@ static int dwc3_gadget_set_ep_config(str
+ if (dwc->gadget.speed == USB_SPEED_FULL)
+ bInterval_m1 = 0;
+
++ if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT &&
++ dwc->gadget.speed == USB_SPEED_FULL)
++ dep->interval = desc->bInterval;
++ else
++ dep->interval = 1 << (desc->bInterval - 1);
++
+ params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1);
+- dep->interval = 1 << (desc->bInterval - 1);
+ }
+
+ return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms);
--- /dev/null
+From a1679af85b2ae35a2b78ad04c18bb069c37330cc Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Mon, 8 Feb 2021 13:53:10 -0800
+Subject: usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit a1679af85b2ae35a2b78ad04c18bb069c37330cc upstream.
+
+Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it must be set
+to 0 when the controller operates in full-speed. See the programming
+guide for DEPCFG command section 3.2.2.1 (v3.30a).
+
+Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/3f57026f993c0ce71498dbb06e49b3a47c4d0265.1612820995.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -593,7 +593,17 @@ static int dwc3_gadget_set_ep_config(str
+ params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1);
+
+ if (desc->bInterval) {
+- params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(desc->bInterval - 1);
++ u8 bInterval_m1;
++
++ /*
++ * Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it
++ * must be set to 0 when the controller operates in full-speed.
++ */
++ bInterval_m1 = min_t(u8, desc->bInterval - 1, 13);
++ if (dwc->gadget.speed == USB_SPEED_FULL)
++ bInterval_m1 = 0;
++
++ params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1);
+ dep->interval = 1 << (desc->bInterval - 1);
+ }
+
--- /dev/null
+From 0eaa1a3714db34a59ce121de5733c3909c529463 Mon Sep 17 00:00:00 2001
+From: Paul Cercueil <paul@crapouillou.net>
+Date: Sat, 23 Jan 2021 14:24:59 +0000
+Subject: usb: musb: Fix runtime PM race in musb_queue_resume_work
+
+From: Paul Cercueil <paul@crapouillou.net>
+
+commit 0eaa1a3714db34a59ce121de5733c3909c529463 upstream.
+
+musb_queue_resume_work() would call the provided callback if the runtime
+PM status was 'active'. Otherwise, it would enqueue the request if the
+hardware was still suspended (musb->is_runtime_suspended is true).
+
+This causes a race with the runtime PM handlers, as it is possible to be
+in the case where the runtime PM status is not yet 'active', but the
+hardware has been awaken (PM resume function has been called).
+
+When hitting the race, the resume work was not enqueued, which probably
+triggered other bugs further down the stack. For instance, a telnet
+connection on Ingenic SoCs would result in a 50/50 chance of a
+segmentation fault somewhere in the musb code.
+
+Rework the code so that either we call the callback directly if
+(musb->is_runtime_suspended == 0), or enqueue the query otherwise.
+
+Fixes: ea2f35c01d5e ("usb: musb: Fix sleeping function called from invalid context for hdrc glue")
+Cc: stable@vger.kernel.org # v4.9+
+Tested-by: Tony Lindgren <tony@atomide.com>
+Reviewed-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Paul Cercueil <paul@crapouillou.net>
+Link: https://lore.kernel.org/r/20210123142502.16980-1-paul@crapouillou.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/musb_core.c | 31 +++++++++++++++++--------------
+ 1 file changed, 17 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2102,32 +2102,35 @@ int musb_queue_resume_work(struct musb *
+ {
+ struct musb_pending_work *w;
+ unsigned long flags;
++ bool is_suspended;
+ int error;
+
+ if (WARN_ON(!callback))
+ return -EINVAL;
+
+- if (pm_runtime_active(musb->controller))
+- return callback(musb, data);
++ spin_lock_irqsave(&musb->list_lock, flags);
++ is_suspended = musb->is_runtime_suspended;
+
+- w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC);
+- if (!w)
+- return -ENOMEM;
++ if (is_suspended) {
++ w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC);
++ if (!w) {
++ error = -ENOMEM;
++ goto out_unlock;
++ }
++
++ w->callback = callback;
++ w->data = data;
+
+- w->callback = callback;
+- w->data = data;
+- spin_lock_irqsave(&musb->list_lock, flags);
+- if (musb->is_runtime_suspended) {
+ list_add_tail(&w->node, &musb->pending_list);
+ error = 0;
+- } else {
+- dev_err(musb->controller, "could not add resume work %p\n",
+- callback);
+- devm_kfree(musb->controller, w);
+- error = -EINPROGRESS;
+ }
++
++out_unlock:
+ spin_unlock_irqrestore(&musb->list_lock, flags);
+
++ if (!is_suspended)
++ error = callback(musb, data);
++
+ return error;
+ }
+ EXPORT_SYMBOL_GPL(musb_queue_resume_work);
--- /dev/null
+From 528222d0c8ce93e435a95cd1e476b60409dd5381 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 26 Jan 2021 14:59:17 +0100
+Subject: USB: serial: ftdi_sio: fix FTX sub-integer prescaler
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 528222d0c8ce93e435a95cd1e476b60409dd5381 upstream.
+
+The most-significant bit of the sub-integer-prescaler index is set in
+the high byte of the baudrate request wIndex also for FTX devices.
+
+This fixes rates like 1152000 which got mapped to 1.2 MBd.
+
+Reported-by: Vladimir <svv75@mail.ru>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=210351
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/ftdi_sio.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -1386,8 +1386,9 @@ static int change_speed(struct tty_struc
+ index_value = get_ftdi_divisor(tty, port);
+ value = (u16)index_value;
+ index = (u16)(index_value >> 16);
+- if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) ||
+- (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) {
++ if (priv->chip_type == FT2232C || priv->chip_type == FT2232H ||
++ priv->chip_type == FT4232H || priv->chip_type == FT232H ||
++ priv->chip_type == FTX) {
+ /* Probably the BM type needs the MSB of the encoded fractional
+ * divider also moved like for the chips above. Any infos? */
+ index = (u16)((index << 8) | priv->interface);
--- /dev/null
+From fea7372cbc40869876df0f045e367f6f97a1666c Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 28 Jan 2021 12:35:23 +0300
+Subject: USB: serial: mos7720: fix error code in mos7720_write()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit fea7372cbc40869876df0f045e367f6f97a1666c upstream.
+
+This code should return -ENOMEM if the kmalloc() fails but instead
+it returns success.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Fixes: 0f64478cbc7a ("USB: add USB serial mos7720 driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/mos7720.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/mos7720.c
++++ b/drivers/usb/serial/mos7720.c
+@@ -1250,8 +1250,10 @@ static int mos7720_write(struct tty_stru
+ if (urb->transfer_buffer == NULL) {
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_ATOMIC);
+- if (!urb->transfer_buffer)
++ if (!urb->transfer_buffer) {
++ bytes_sent = -ENOMEM;
+ goto exit;
++ }
+ }
+ transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
+
--- /dev/null
+From a70aa7dc60099bbdcbd6faca42a915d80f31161e Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 26 Jan 2021 13:26:54 +0300
+Subject: USB: serial: mos7840: fix error code in mos7840_write()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit a70aa7dc60099bbdcbd6faca42a915d80f31161e upstream.
+
+This should return -ENOMEM instead of 0 if the kmalloc() fails.
+
+Fixes: 3f5429746d91 ("USB: Moschip 7840 USB-Serial Driver")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/mos7840.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/mos7840.c
++++ b/drivers/usb/serial/mos7840.c
+@@ -1330,8 +1330,10 @@ static int mos7840_write(struct tty_stru
+ if (urb->transfer_buffer == NULL) {
+ urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+ GFP_ATOMIC);
+- if (!urb->transfer_buffer)
++ if (!urb->transfer_buffer) {
++ bytes_sent = -ENOMEM;
+ goto exit;
++ }
+ }
+ transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
+
--- /dev/null
+From 6420a569504e212d618d4a4736e2c59ed80a8478 Mon Sep 17 00:00:00 2001
+From: Lech Perczak <lech.perczak@gmail.com>
+Date: Sun, 7 Feb 2021 01:54:43 +0100
+Subject: USB: serial: option: update interface mapping for ZTE P685M
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lech Perczak <lech.perczak@gmail.com>
+
+commit 6420a569504e212d618d4a4736e2c59ed80a8478 upstream.
+
+This patch prepares for qmi_wwan driver support for the device.
+Previously "option" driver mapped itself to interfaces 0 and 3 (matching
+ff/ff/ff), while interface 3 is in fact a QMI port.
+Interfaces 1 and 2 (matching ff/00/00) expose AT commands,
+and weren't supported previously at all.
+Without this patch, a possible conflict would exist if device ID was
+added to qmi_wwan driver for interface 3.
+
+Update and simplify device ID to match interfaces 0-2 directly,
+to expose QCDM (0), PCUI (1), and modem (2) ports and avoid conflict
+with QMI (3), and ADB (4).
+
+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
+
+Cc: Johan Hovold <johan@kernel.org>
+Cc: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Lech Perczak <lech.perczak@gmail.com>
+Link: https://lore.kernel.org/r/20210207005443.12936-1-lech.perczak@gmail.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/option.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1569,7 +1569,8 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1274, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1275, 0xff, 0xff, 0xff) },
++ { USB_DEVICE(ZTE_VENDOR_ID, 0x1275), /* ZTE P685M */
++ .driver_info = RSVD(3) | RSVD(4) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1276, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1277, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1278, 0xff, 0xff, 0xff) },