--- /dev/null
+From 44dd5e2106dc2fd01697b539085818d1d1c58df0 Mon Sep 17 00:00:00 2001
+From: Cameron Nemo <cnemo@tutanota.com>
+Date: Tue, 9 Feb 2021 20:23:49 +0100
+Subject: arm64: dts: rockchip: add rk3328 dwc3 usb controller node
+
+From: Cameron Nemo <cnemo@tutanota.com>
+
+commit 44dd5e2106dc2fd01697b539085818d1d1c58df0 upstream.
+
+RK3328 SoCs have one USB 3.0 OTG controller which uses DWC_USB3
+core's general architecture. It can act as static xHCI host
+controller, static device controller, USB 3.0/2.0 OTG basing
+on ID of USB3.0 PHY.
+
+Signed-off-by: William Wu <william.wu@rock-chips.com>
+Signed-off-by: Cameron Nemo <cnemo@tutanota.com>
+Signed-off-by: Johan Jonker <jbx6244@gmail.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://lore.kernel.org/r/20210209192350.7130-7-jbx6244@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/boot/dts/rockchip/rk3328.dtsi | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+@@ -984,6 +984,25 @@
+ status = "disabled";
+ };
+
++ usbdrd3: usb@ff600000 {
++ compatible = "rockchip,rk3328-dwc3", "snps,dwc3";
++ reg = <0x0 0xff600000 0x0 0x100000>;
++ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cru SCLK_USB3OTG_REF>, <&cru SCLK_USB3OTG_SUSPEND>,
++ <&cru ACLK_USB3OTG>;
++ clock-names = "ref_clk", "suspend_clk",
++ "bus_clk";
++ dr_mode = "otg";
++ phy_type = "utmi_wide";
++ snps,dis-del-phy-power-chg-quirk;
++ snps,dis_enblslpm_quirk;
++ snps,dis-tx-ipgap-linecheck-quirk;
++ snps,dis-u2-freeclk-exists-quirk;
++ snps,dis_u2_susphy_quirk;
++ snps,dis_u3_susphy_quirk;
++ status = "disabled";
++ };
++
+ gic: interrupt-controller@ff811000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
--- /dev/null
+From bbac8bd65f5402281cb7b0452c1c5f367387b459 Mon Sep 17 00:00:00 2001
+From: Cameron Nemo <cnemo@tutanota.com>
+Date: Tue, 4 May 2021 16:36:13 +0800
+Subject: arm64: dts: rockchip: Enable USB3 for rk3328 Rock64
+
+From: Cameron Nemo <cnemo@tutanota.com>
+
+commit bbac8bd65f5402281cb7b0452c1c5f367387b459 upstream.
+
+Enable USB3 nodes for the rk3328-based PINE Rock64 board.
+
+The separate power regulator is not added as it is controlled by the
+same GPIO line as the existing VBUS regulators, so it is already
+enabled. Also there is no port representation to tie the regulator to.
+
+[wens@csie.org: Rebased onto v5.12]
+
+Signed-off-by: Cameron Nemo <cnemo@tutanota.com>
+[wens@csie.org: Rewrote commit message]
+Signed-off-by: Chen-Yu Tsai <wens@csie.org>
+Link: https://lore.kernel.org/r/20210504083616.9654-2-wens@kernel.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/boot/dts/rockchip/rk3328-rock64.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+@@ -384,6 +384,11 @@
+ status = "okay";
+ };
+
++&usbdrd3 {
++ dr_mode = "host";
++ status = "okay";
++};
++
+ &usb_host0_ehci {
+ status = "okay";
+ };
--- /dev/null
+From 59ec8e2fa5aaed6afd18d5362dc131aab92406e7 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 8 Dec 2020 09:52:57 +0200
+Subject: ath11k: unlock on error path in ath11k_mac_op_add_interface()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 59ec8e2fa5aaed6afd18d5362dc131aab92406e7 upstream.
+
+These error paths need to drop the &ar->conf_mutex before returning.
+
+Fixes: 690ace20ff79 ("ath11k: peer delete synchronization with firmware")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Link: https://lore.kernel.org/r/X85sVGVP/0XvlrEJ@mwanda
+Signed-off-by: Nobuhiro Iwamatsu (CIP) <nobuhiro1.iwamatsu@toshiba.co.jp>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/ath/ath11k/mac.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -4603,13 +4603,13 @@ err_peer_del:
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
+ arvif->vdev_id, vif->addr);
+- return ret;
++ goto err;
+ }
+
+ ret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id,
+ vif->addr);
+ if (ret)
+- return ret;
++ goto err;
+
+ ar->num_peers--;
+ }
--- /dev/null
+From foo@baz Thu Jul 15 01:10:15 PM CEST 2021
+From: Hanjun Guo <guohanjun@huawei.com>
+Date: Tue, 13 Jul 2021 17:18:35 +0800
+Subject: io_uring: convert io_buffer_idr to XArray
+To: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, Jens Axboe <axboe@kernel.dk>, Matthew Wilcox <willy@infradead.org>, yangerkun <yangerkun@huawei.com>, Hanjun Guo <guohanjun@huawei.com>
+Message-ID: <1626167917-11972-6-git-send-email-guohanjun@huawei.com>
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit 9e15c3a0ced5a61f320b989072c24983cb1620c1 upstream.
+
+Like we did for the personality idr, convert the IO buffer idr to use
+XArray. This avoids a use-after-free on removal of entries, since idr
+doesn't like doing so from inside an iterator, and it nicely reduces
+the amount of code we need to support this feature.
+
+Fixes: 5a2e745d4d43 ("io_uring: buffer registration infrastructure")
+Cc: stable@vger.kernel.org
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: yangerkun <yangerkun@huawei.com>
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c | 43 +++++++++++++++----------------------------
+ 1 file changed, 15 insertions(+), 28 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -344,7 +344,7 @@ struct io_ring_ctx {
+ struct socket *ring_sock;
+ #endif
+
+- struct idr io_buffer_idr;
++ struct xarray io_buffers;
+
+ struct xarray personalities;
+ u32 pers_next;
+@@ -1212,7 +1212,7 @@ static struct io_ring_ctx *io_ring_ctx_a
+ INIT_LIST_HEAD(&ctx->cq_overflow_list);
+ init_completion(&ctx->ref_comp);
+ init_completion(&ctx->sq_thread_comp);
+- idr_init(&ctx->io_buffer_idr);
++ xa_init_flags(&ctx->io_buffers, XA_FLAGS_ALLOC1);
+ xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);
+ mutex_init(&ctx->uring_lock);
+ init_waitqueue_head(&ctx->wait);
+@@ -2990,7 +2990,7 @@ static struct io_buffer *io_buffer_selec
+
+ lockdep_assert_held(&req->ctx->uring_lock);
+
+- head = idr_find(&req->ctx->io_buffer_idr, bgid);
++ head = xa_load(&req->ctx->io_buffers, bgid);
+ if (head) {
+ if (!list_empty(&head->list)) {
+ kbuf = list_last_entry(&head->list, struct io_buffer,
+@@ -2998,7 +2998,7 @@ static struct io_buffer *io_buffer_selec
+ list_del(&kbuf->list);
+ } else {
+ kbuf = head;
+- idr_remove(&req->ctx->io_buffer_idr, bgid);
++ xa_erase(&req->ctx->io_buffers, bgid);
+ }
+ if (*len > kbuf->len)
+ *len = kbuf->len;
+@@ -3960,7 +3960,7 @@ static int __io_remove_buffers(struct io
+ }
+ i++;
+ kfree(buf);
+- idr_remove(&ctx->io_buffer_idr, bgid);
++ xa_erase(&ctx->io_buffers, bgid);
+
+ return i;
+ }
+@@ -3978,7 +3978,7 @@ static int io_remove_buffers(struct io_k
+ lockdep_assert_held(&ctx->uring_lock);
+
+ ret = -ENOENT;
+- head = idr_find(&ctx->io_buffer_idr, p->bgid);
++ head = xa_load(&ctx->io_buffers, p->bgid);
+ if (head)
+ ret = __io_remove_buffers(ctx, head, p->bgid, p->nbufs);
+ if (ret < 0)
+@@ -4069,21 +4069,14 @@ static int io_provide_buffers(struct io_
+
+ lockdep_assert_held(&ctx->uring_lock);
+
+- list = head = idr_find(&ctx->io_buffer_idr, p->bgid);
++ list = head = xa_load(&ctx->io_buffers, p->bgid);
+
+ ret = io_add_buffers(p, &head);
+- if (ret < 0)
+- goto out;
+-
+- if (!list) {
+- ret = idr_alloc(&ctx->io_buffer_idr, head, p->bgid, p->bgid + 1,
+- GFP_KERNEL);
+- if (ret < 0) {
++ if (ret >= 0 && !list) {
++ ret = xa_insert(&ctx->io_buffers, p->bgid, head, GFP_KERNEL);
++ if (ret < 0)
+ __io_remove_buffers(ctx, head, p->bgid, -1U);
+- goto out;
+- }
+ }
+-out:
+ if (ret < 0)
+ req_set_fail_links(req);
+
+@@ -8411,19 +8404,13 @@ static int io_eventfd_unregister(struct
+ return -ENXIO;
+ }
+
+-static int __io_destroy_buffers(int id, void *p, void *data)
+-{
+- struct io_ring_ctx *ctx = data;
+- struct io_buffer *buf = p;
+-
+- __io_remove_buffers(ctx, buf, id, -1U);
+- return 0;
+-}
+-
+ static void io_destroy_buffers(struct io_ring_ctx *ctx)
+ {
+- idr_for_each(&ctx->io_buffer_idr, __io_destroy_buffers, ctx);
+- idr_destroy(&ctx->io_buffer_idr);
++ struct io_buffer *buf;
++ unsigned long index;
++
++ xa_for_each(&ctx->io_buffers, index, buf)
++ __io_remove_buffers(ctx, buf, index, -1U);
+ }
+
+ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
--- /dev/null
+From foo@baz Thu Jul 15 01:10:15 PM CEST 2021
+From: Hanjun Guo <guohanjun@huawei.com>
+Date: Tue, 13 Jul 2021 17:18:34 +0800
+Subject: io_uring: Convert personality_idr to XArray
+To: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Pavel Begunkov <asml.silence@gmail.com>, Jens Axboe <axboe@kernel.dk>, Hanjun Guo <guohanjun@huawei.com>
+Message-ID: <1626167917-11972-5-git-send-email-guohanjun@huawei.com>
+
+From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+
+commit 61cf93700fe6359552848ed5e3becba6cd760efa upstream.
+
+You can't call idr_remove() from within a idr_for_each() callback,
+but you can call xa_erase() from an xa_for_each() loop, so switch the
+entire personality_idr from the IDR to the XArray. This manifests as a
+use-after-free as idr_for_each() attempts to walk the rest of the node
+after removing the last entry from it.
+
+Fixes: 071698e13ac6 ("io_uring: allow registering credentials")
+Cc: stable@vger.kernel.org # 5.6+
+Reported-by: yangerkun <yangerkun@huawei.com>
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+[Pavel: rebased (creds load was moved into io_init_req())]
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/7ccff36e1375f2b0ebf73d957f037b43becc0dde.1615212806.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c | 59 +++++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 30 insertions(+), 29 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -346,7 +346,8 @@ struct io_ring_ctx {
+
+ struct idr io_buffer_idr;
+
+- struct idr personality_idr;
++ struct xarray personalities;
++ u32 pers_next;
+
+ struct {
+ unsigned cached_cq_tail;
+@@ -1212,7 +1213,7 @@ static struct io_ring_ctx *io_ring_ctx_a
+ init_completion(&ctx->ref_comp);
+ init_completion(&ctx->sq_thread_comp);
+ idr_init(&ctx->io_buffer_idr);
+- idr_init(&ctx->personality_idr);
++ xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);
+ mutex_init(&ctx->uring_lock);
+ init_waitqueue_head(&ctx->wait);
+ spin_lock_init(&ctx->completion_lock);
+@@ -6629,7 +6630,7 @@ static int io_init_req(struct io_ring_ct
+ if (id) {
+ struct io_identity *iod;
+
+- iod = idr_find(&ctx->personality_idr, id);
++ iod = xa_load(&ctx->personalities, id);
+ if (unlikely(!iod))
+ return -EINVAL;
+ refcount_inc(&iod->count);
+@@ -8445,7 +8446,6 @@ static void io_ring_ctx_free(struct io_r
+ io_sqe_files_unregister(ctx);
+ io_eventfd_unregister(ctx);
+ io_destroy_buffers(ctx);
+- idr_destroy(&ctx->personality_idr);
+
+ #if defined(CONFIG_UNIX)
+ if (ctx->ring_sock) {
+@@ -8509,7 +8509,7 @@ static int io_unregister_personality(str
+ {
+ struct io_identity *iod;
+
+- iod = idr_remove(&ctx->personality_idr, id);
++ iod = xa_erase(&ctx->personalities, id);
+ if (iod) {
+ put_cred(iod->creds);
+ if (refcount_dec_and_test(&iod->count))
+@@ -8520,14 +8520,6 @@ static int io_unregister_personality(str
+ return -EINVAL;
+ }
+
+-static int io_remove_personalities(int id, void *p, void *data)
+-{
+- struct io_ring_ctx *ctx = data;
+-
+- io_unregister_personality(ctx, id);
+- return 0;
+-}
+-
+ static void io_ring_exit_work(struct work_struct *work)
+ {
+ struct io_ring_ctx *ctx = container_of(work, struct io_ring_ctx,
+@@ -8554,6 +8546,9 @@ static bool io_cancel_ctx_cb(struct io_w
+
+ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
+ {
++ unsigned long index;
++ struct io_identify *iod;
++
+ mutex_lock(&ctx->uring_lock);
+ percpu_ref_kill(&ctx->refs);
+ /* if force is set, the ring is going away. always drop after that */
+@@ -8574,7 +8569,8 @@ static void io_ring_ctx_wait_and_kill(st
+
+ /* if we failed setting up the ctx, we might not have any rings */
+ io_iopoll_try_reap_events(ctx);
+- idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx);
++ xa_for_each(&ctx->personalities, index, iod)
++ io_unregister_personality(ctx, index);
+
+ /*
+ * Do this upfront, so we won't have a grace period where the ring
+@@ -9137,11 +9133,10 @@ out_fput:
+ }
+
+ #ifdef CONFIG_PROC_FS
+-static int io_uring_show_cred(int id, void *p, void *data)
++static int io_uring_show_cred(struct seq_file *m, unsigned int id,
++ const struct io_identity *iod)
+ {
+- struct io_identity *iod = p;
+ const struct cred *cred = iod->creds;
+- struct seq_file *m = data;
+ struct user_namespace *uns = seq_user_ns(m);
+ struct group_info *gi;
+ kernel_cap_t cap;
+@@ -9209,9 +9204,13 @@ static void __io_uring_show_fdinfo(struc
+ seq_printf(m, "%5u: 0x%llx/%u\n", i, buf->ubuf,
+ (unsigned int) buf->len);
+ }
+- if (has_lock && !idr_is_empty(&ctx->personality_idr)) {
++ if (has_lock && !xa_empty(&ctx->personalities)) {
++ unsigned long index;
++ const struct io_identity *iod;
++
+ seq_printf(m, "Personalities:\n");
+- idr_for_each(&ctx->personality_idr, io_uring_show_cred, m);
++ xa_for_each(&ctx->personalities, index, iod)
++ io_uring_show_cred(m, index, iod);
+ }
+ seq_printf(m, "PollList:\n");
+ spin_lock_irq(&ctx->completion_lock);
+@@ -9597,21 +9596,23 @@ out:
+
+ static int io_register_personality(struct io_ring_ctx *ctx)
+ {
+- struct io_identity *id;
++ struct io_identity *iod;
++ u32 id;
+ int ret;
+
+- id = kmalloc(sizeof(*id), GFP_KERNEL);
+- if (unlikely(!id))
++ iod = kmalloc(sizeof(*iod), GFP_KERNEL);
++ if (unlikely(!iod))
+ return -ENOMEM;
+
+- io_init_identity(id);
+- id->creds = get_current_cred();
++ io_init_identity(iod);
++ iod->creds = get_current_cred();
+
+- ret = idr_alloc_cyclic(&ctx->personality_idr, id, 1, USHRT_MAX, GFP_KERNEL);
+- if (ret < 0) {
+- put_cred(id->creds);
+- kfree(id);
+- }
++ ret = xa_alloc_cyclic(&ctx->personalities, &id, (void *)iod,
++ XA_LIMIT(0, USHRT_MAX), &ctx->pers_next, GFP_KERNEL);
++ if (!ret)
++ return id;
++ put_cred(iod->creds);
++ kfree(iod);
+ return ret;
+ }
+
--- /dev/null
+From foo@baz Thu Jul 15 01:10:15 PM CEST 2021
+From: Hanjun Guo <guohanjun@huawei.com>
+Date: Tue, 13 Jul 2021 17:18:33 +0800
+Subject: io_uring: simplify io_remove_personalities()
+To: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, Yejune Deng <yejune.deng@gmail.com>, Jens Axboe <axboe@kernel.dk>, Hanjun Guo <guohanjun@huawei.com>
+Message-ID: <1626167917-11972-4-git-send-email-guohanjun@huawei.com>
+
+From: Yejune Deng <yejune.deng@gmail.com>
+
+commit 0bead8cd39b9c9c7c4e902018ccf129107ac50ef upstream.
+
+The function io_remove_personalities() is very similar to
+io_unregister_personality(),so implement io_remove_personalities()
+calling io_unregister_personality().
+
+Signed-off-by: Yejune Deng <yejune.deng@gmail.com>
+Reviewed-by: Pavel Begunkov <asml.silence@gmail.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c | 28 +++++++++++-----------------
+ 1 file changed, 11 insertions(+), 17 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -8505,9 +8505,8 @@ static int io_uring_fasync(int fd, struc
+ return fasync_helper(fd, file, on, &ctx->cq_fasync);
+ }
+
+-static int io_remove_personalities(int id, void *p, void *data)
++static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id)
+ {
+- struct io_ring_ctx *ctx = data;
+ struct io_identity *iod;
+
+ iod = idr_remove(&ctx->personality_idr, id);
+@@ -8515,7 +8514,17 @@ static int io_remove_personalities(int i
+ put_cred(iod->creds);
+ if (refcount_dec_and_test(&iod->count))
+ kfree(iod);
++ return 0;
+ }
++
++ return -EINVAL;
++}
++
++static int io_remove_personalities(int id, void *p, void *data)
++{
++ struct io_ring_ctx *ctx = data;
++
++ io_unregister_personality(ctx, id);
+ return 0;
+ }
+
+@@ -9606,21 +9615,6 @@ static int io_register_personality(struc
+ return ret;
+ }
+
+-static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id)
+-{
+- struct io_identity *iod;
+-
+- iod = idr_remove(&ctx->personality_idr, id);
+- if (iod) {
+- put_cred(iod->creds);
+- if (refcount_dec_and_test(&iod->count))
+- kfree(iod);
+- return 0;
+- }
+-
+- return -EINVAL;
+-}
+-
+ static int io_register_restrictions(struct io_ring_ctx *ctx, void __user *arg,
+ unsigned int nr_args)
+ {
--- /dev/null
+From 4ceddce55eb35d15b0f87f5dcf6f0058fd15d3a4 Mon Sep 17 00:00:00 2001
+From: Mauricio Faria de Oliveira <mfo@canonical.com>
+Date: Mon, 22 Feb 2021 12:41:23 -0300
+Subject: loop: fix I/O error on fsync() in detached loop devices
+
+From: Mauricio Faria de Oliveira <mfo@canonical.com>
+
+commit 4ceddce55eb35d15b0f87f5dcf6f0058fd15d3a4 upstream.
+
+There's an I/O error on fsync() in a detached loop device
+if it has been previously attached.
+
+The issue is write cache is enabled in the attach path in
+loop_configure() but it isn't disabled in the detach path;
+thus it remains enabled in the block device regardless of
+whether it is attached or not.
+
+Now fsync() can get an I/O request that will just be failed
+later in loop_queue_rq() as device's state is not 'Lo_bound'.
+
+So, disable write cache in the detach path.
+
+Do so based on the queue flag, not the loop device flag for
+read-only (used to enable) as the queue flag can be changed
+via sysfs even on read-only loop devices (e.g., losetup -r.)
+
+Test-case:
+
+ # DEV=/dev/loop7
+
+ # IMG=/tmp/image
+ # truncate --size 1M $IMG
+
+ # losetup $DEV $IMG
+ # losetup -d $DEV
+
+Before:
+
+ # strace -e fsync parted -s $DEV print 2>&1 | grep fsync
+ fsync(3) = -1 EIO (Input/output error)
+ Warning: Error fsyncing/closing /dev/loop7: Input/output error
+ [ 982.529929] blk_update_request: I/O error, dev loop7, sector 0 op 0x1:(WRITE) flags 0x800 phys_seg 0 prio class 0
+
+After:
+
+ # strace -e fsync parted -s $DEV print 2>&1 | grep fsync
+ fsync(3) = 0
+
+Co-developed-by: Eric Desrochers <eric.desrochers@canonical.com>
+Signed-off-by: Eric Desrochers <eric.desrochers@canonical.com>
+Signed-off-by: Mauricio Faria de Oliveira <mfo@canonical.com>
+Tested-by: Gabriel Krisman Bertazi <krisman@collabora.com>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/loop.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -1224,6 +1224,9 @@ static int __loop_clr_fd(struct loop_dev
+ goto out_unlock;
+ }
+
++ if (test_bit(QUEUE_FLAG_WC, &lo->lo_queue->queue_flags))
++ blk_queue_write_cache(lo->lo_queue, false, false);
++
+ /* freeze request queue during the transition */
+ blk_mq_freeze_queue(lo->lo_queue);
+
--- /dev/null
+From cad065ed8d8831df67b9754cc4437ed55d8b48c0 Mon Sep 17 00:00:00 2001
+From: Paul Cercueil <paul@crapouillou.net>
+Date: Fri, 25 Jun 2021 11:49:29 +0100
+Subject: MIPS: MT extensions are not available on MIPS32r1
+
+From: Paul Cercueil <paul@crapouillou.net>
+
+commit cad065ed8d8831df67b9754cc4437ed55d8b48c0 upstream.
+
+MIPS MT extensions were added with the MIPS 34K processor, which was
+based on the MIPS32r2 ISA.
+
+This fixes a build error when building a generic kernel for a MIPS32r1
+CPU.
+
+Fixes: c434b9f80b09 ("MIPS: Kconfig: add MIPS_GENERIC_KERNEL symbol")
+Cc: stable@vger.kernel.org # v5.9
+Signed-off-by: Paul Cercueil <paul@crapouillou.net>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/mips/include/asm/cpu-features.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/include/asm/cpu-features.h
++++ b/arch/mips/include/asm/cpu-features.h
+@@ -64,6 +64,8 @@
+ ((MIPS_ISA_REV >= (ge)) && (MIPS_ISA_REV < (lt)))
+ #define __isa_range_or_flag(ge, lt, flag) \
+ (__isa_range(ge, lt) || ((MIPS_ISA_REV < (lt)) && __isa(flag)))
++#define __isa_range_and_ase(ge, lt, ase) \
++ (__isa_range(ge, lt) && __ase(ase))
+
+ /*
+ * SMP assumption: Options of CPU 0 are a superset of all processors.
+@@ -423,7 +425,7 @@
+ #endif
+
+ #ifndef cpu_has_mipsmt
+-#define cpu_has_mipsmt __isa_lt_and_ase(6, MIPS_ASE_MIPSMT)
++#define cpu_has_mipsmt __isa_range_and_ase(2, 6, MIPS_ASE_MIPSMT)
+ #endif
+
+ #ifndef cpu_has_vp
--- /dev/null
+From foo@baz Thu Jul 15 01:10:15 PM CEST 2021
+From: Hanjun Guo <guohanjun@huawei.com>
+Date: Tue, 13 Jul 2021 17:18:32 +0800
+Subject: mm,hwpoison: return -EBUSY when migration fails
+To: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, Oscar Salvador <osalvador@suse.de>, David Hildenbrand <david@redhat.com>, Andrew Morton <akpm@linux-foundation.org>, Linus Torvalds <torvalds@linux-foundation.org>, Hanjun Guo <guohanjun@huawei.com>
+Message-ID: <1626167917-11972-3-git-send-email-guohanjun@huawei.com>
+
+From: Oscar Salvador <osalvador@suse.de>
+
+commit 3f4b815a439adfb8f238335612c4b28bc10084d8
+
+Currently, we return -EIO when we fail to migrate the page.
+
+Migrations' failures are rather transient as they can happen due to
+several reasons, e.g: high page refcount bump, mapping->migrate_page
+failing etc. All meaning that at that time the page could not be
+migrated, but that has nothing to do with an EIO error.
+
+Let us return -EBUSY instead, as we do in case we failed to isolate the
+page.
+
+While are it, let us remove the "ret" print as its value does not change.
+
+Link: https://lkml.kernel.org/r/20201209092818.30417-1-osalvador@suse.de
+Signed-off-by: Oscar Salvador <osalvador@suse.de>
+Acked-by: Naoya Horiguchi <naoya.horiguchi@nec.com>
+Acked-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: David Hildenbrand <david@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memory-failure.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -1856,11 +1856,11 @@ static int __soft_offline_page(struct pa
+ pr_info("soft offline: %#lx: %s migration failed %d, type %lx (%pGp)\n",
+ pfn, msg_page[huge], ret, page->flags, &page->flags);
+ if (ret > 0)
+- ret = -EIO;
++ ret = -EBUSY;
+ }
+ } else {
+- pr_info("soft offline: %#lx: %s isolation failed: %d, page count %d, type %lx (%pGp)\n",
+- pfn, msg_page[huge], ret, page_count(page), page->flags, &page->flags);
++ pr_info("soft offline: %#lx: %s isolation failed, page count %d, type %lx (%pGp)\n",
++ pfn, msg_page[huge], page_count(page), page->flags, &page->flags);
+ ret = -EBUSY;
+ }
+ return ret;
--- /dev/null
+From 122e093c1734361dedb64f65c99b93e28e4624f4 Mon Sep 17 00:00:00 2001
+From: Mike Rapoport <rppt@kernel.org>
+Date: Mon, 28 Jun 2021 19:33:26 -0700
+Subject: mm/page_alloc: fix memory map initialization for descending nodes
+
+From: Mike Rapoport <rppt@linux.ibm.com>
+
+commit 122e093c1734361dedb64f65c99b93e28e4624f4 upstream.
+
+On systems with memory nodes sorted in descending order, for instance Dell
+Precision WorkStation T5500, the struct pages for higher PFNs and
+respectively lower nodes, could be overwritten by the initialization of
+struct pages corresponding to the holes in the memory sections.
+
+For example for the below memory layout
+
+[ 0.245624] Early memory node ranges
+[ 0.248496] node 1: [mem 0x0000000000001000-0x0000000000090fff]
+[ 0.251376] node 1: [mem 0x0000000000100000-0x00000000dbdf8fff]
+[ 0.254256] node 1: [mem 0x0000000100000000-0x0000001423ffffff]
+[ 0.257144] node 0: [mem 0x0000001424000000-0x0000002023ffffff]
+
+the range 0x1424000000 - 0x1428000000 in the beginning of node 0 starts in
+the middle of a section and will be considered as a hole during the
+initialization of the last section in node 1.
+
+The wrong initialization of the memory map causes panic on boot when
+CONFIG_DEBUG_VM is enabled.
+
+Reorder loop order of the memory map initialization so that the outer loop
+will always iterate over populated memory regions in the ascending order
+and the inner loop will select the zone corresponding to the PFN range.
+
+This way initialization of the struct pages for the memory holes will be
+always done for the ranges that are actually not populated.
+
+[akpm@linux-foundation.org: coding style fixes]
+
+Link: https://lkml.kernel.org/r/YNXlMqBbL+tBG7yq@kernel.org
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=213073
+Link: https://lkml.kernel.org/r/20210624062305.10940-1-rppt@kernel.org
+Fixes: 0740a50b9baa ("mm/page_alloc.c: refactor initialization of struct page for holes in memory layout")
+Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
+Cc: Boris Petkov <bp@alien8.de>
+Cc: Robert Shteynfeld <robert.shteynfeld@gmail.com>
+Cc: Baoquan He <bhe@redhat.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/page_alloc.c | 100 +++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 60 insertions(+), 40 deletions(-)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -6129,7 +6129,7 @@ void __ref memmap_init_zone_device(struc
+ return;
+
+ /*
+- * The call to memmap_init_zone should have already taken care
++ * The call to memmap_init should have already taken care
+ * of the pages reserved for the memmap, so we can just jump to
+ * the end of that region and start processing the device pages.
+ */
+@@ -6194,7 +6194,7 @@ static void __meminit zone_init_free_lis
+ /*
+ * Only struct pages that correspond to ranges defined by memblock.memory
+ * are zeroed and initialized by going through __init_single_page() during
+- * memmap_init_zone().
++ * memmap_init_zone_range().
+ *
+ * But, there could be struct pages that correspond to holes in
+ * memblock.memory. This can happen because of the following reasons:
+@@ -6213,9 +6213,9 @@ static void __meminit zone_init_free_lis
+ * zone/node above the hole except for the trailing pages in the last
+ * section that will be appended to the zone/node below.
+ */
+-static u64 __meminit init_unavailable_range(unsigned long spfn,
+- unsigned long epfn,
+- int zone, int node)
++static void __init init_unavailable_range(unsigned long spfn,
++ unsigned long epfn,
++ int zone, int node)
+ {
+ unsigned long pfn;
+ u64 pgcnt = 0;
+@@ -6231,58 +6231,77 @@ static u64 __meminit init_unavailable_ra
+ pgcnt++;
+ }
+
+- return pgcnt;
++ if (pgcnt)
++ pr_info("On node %d, zone %s: %lld pages in unavailable ranges",
++ node, zone_names[zone], pgcnt);
+ }
+ #else
+-static inline u64 init_unavailable_range(unsigned long spfn, unsigned long epfn,
+- int zone, int node)
++static inline void init_unavailable_range(unsigned long spfn,
++ unsigned long epfn,
++ int zone, int node)
+ {
+- return 0;
+ }
+ #endif
+
+-void __meminit __weak memmap_init(unsigned long size, int nid,
+- unsigned long zone,
+- unsigned long range_start_pfn)
++static void __init memmap_init_zone_range(struct zone *zone,
++ unsigned long start_pfn,
++ unsigned long end_pfn,
++ unsigned long *hole_pfn)
++{
++ unsigned long zone_start_pfn = zone->zone_start_pfn;
++ unsigned long zone_end_pfn = zone_start_pfn + zone->spanned_pages;
++ int nid = zone_to_nid(zone), zone_id = zone_idx(zone);
++
++ start_pfn = clamp(start_pfn, zone_start_pfn, zone_end_pfn);
++ end_pfn = clamp(end_pfn, zone_start_pfn, zone_end_pfn);
++
++ if (start_pfn >= end_pfn)
++ return;
++
++ memmap_init_zone(end_pfn - start_pfn, nid, zone_id, start_pfn,
++ zone_end_pfn, MEMINIT_EARLY, NULL, MIGRATE_MOVABLE);
++
++ if (*hole_pfn < start_pfn)
++ init_unavailable_range(*hole_pfn, start_pfn, zone_id, nid);
++
++ *hole_pfn = end_pfn;
++}
++
++void __init __weak memmap_init(void)
+ {
+- static unsigned long hole_pfn;
+ unsigned long start_pfn, end_pfn;
+- unsigned long range_end_pfn = range_start_pfn + size;
+- int i;
+- u64 pgcnt = 0;
++ unsigned long hole_pfn = 0;
++ int i, j, zone_id, nid;
+
+- for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
+- start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
+- end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
++ for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
++ struct pglist_data *node = NODE_DATA(nid);
+
+- if (end_pfn > start_pfn) {
+- size = end_pfn - start_pfn;
+- memmap_init_zone(size, nid, zone, start_pfn, range_end_pfn,
+- MEMINIT_EARLY, NULL, MIGRATE_MOVABLE);
+- }
++ for (j = 0; j < MAX_NR_ZONES; j++) {
++ struct zone *zone = node->node_zones + j;
+
+- if (hole_pfn < start_pfn)
+- pgcnt += init_unavailable_range(hole_pfn, start_pfn,
+- zone, nid);
+- hole_pfn = end_pfn;
++ if (!populated_zone(zone))
++ continue;
++
++ memmap_init_zone_range(zone, start_pfn, end_pfn,
++ &hole_pfn);
++ zone_id = j;
++ }
+ }
+
+ #ifdef CONFIG_SPARSEMEM
+ /*
+- * Initialize the hole in the range [zone_end_pfn, section_end].
+- * If zone boundary falls in the middle of a section, this hole
+- * will be re-initialized during the call to this function for the
+- * higher zone.
++ * Initialize the memory map for hole in the range [memory_end,
++ * section_end].
++ * Append the pages in this hole to the highest zone in the last
++ * node.
++ * The call to init_unavailable_range() is outside the ifdef to
++ * silence the compiler warining about zone_id set but not used;
++ * for FLATMEM it is a nop anyway
+ */
+- end_pfn = round_up(range_end_pfn, PAGES_PER_SECTION);
++ end_pfn = round_up(end_pfn, PAGES_PER_SECTION);
+ if (hole_pfn < end_pfn)
+- pgcnt += init_unavailable_range(hole_pfn, end_pfn,
+- zone, nid);
+ #endif
+-
+- if (pgcnt)
+- pr_info(" %s zone: %llu pages in unavailable ranges\n",
+- zone_names[zone], pgcnt);
++ init_unavailable_range(hole_pfn, end_pfn, zone_id, nid);
+ }
+
+ static int zone_batchsize(struct zone *zone)
+@@ -6981,7 +7000,6 @@ static void __init free_area_init_core(s
+ set_pageblock_order();
+ setup_usemap(pgdat, zone, zone_start_pfn, size);
+ init_currently_empty_zone(zone, zone_start_pfn, size);
+- memmap_init(size, nid, j, zone_start_pfn);
+ }
+ }
+
+@@ -7507,6 +7525,8 @@ void __init free_area_init(unsigned long
+ node_set_state(nid, N_MEMORY);
+ check_for_memory(pgdat, nid);
+ }
++
++ memmap_init();
+ }
+
+ static int __init cmdline_parse_core(char *p, unsigned long *core,
--- /dev/null
+From foo@baz Thu Jul 15 01:10:15 PM CEST 2021
+From: Hanjun Guo <guohanjun@huawei.com>
+Date: Tue, 13 Jul 2021 17:18:37 +0800
+Subject: scsi: iscsi: Fix iSCSI cls conn state
+To: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, Mike Christie <michael.christie@oracle.com>, Gulam Mohamed <gulam.mohamed@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Hanjun Guo <guohanjun@huawei.com>
+Message-ID: <1626167917-11972-8-git-send-email-guohanjun@huawei.com>
+
+From: Mike Christie <michael.christie@oracle.com>
+
+commit 0dcf8febcb7b9d42bec98bc068e01d1a6ea578b8 upstream.
+
+In commit 9e67600ed6b8 ("scsi: iscsi: Fix race condition between login and
+sync thread") I missed that libiscsi was now setting the iSCSI class state,
+and that patch ended up resetting the state during conn stoppage and using
+the wrong state value during ep_disconnect. This patch moves the setting of
+the class state to the class module and then fixes the two issues above.
+
+Link: https://lore.kernel.org/r/20210406171746.5016-1-michael.christie@oracle.com
+Fixes: 9e67600ed6b8 ("scsi: iscsi: Fix race condition between login and sync thread")
+Cc: Gulam Mohamed <gulam.mohamed@oracle.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/libiscsi.c | 26 +++-----------------------
+ drivers/scsi/scsi_transport_iscsi.c | 18 +++++++++++++++---
+ 2 files changed, 18 insertions(+), 26 deletions(-)
+
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -3089,9 +3089,10 @@ fail_mgmt_tasks(struct iscsi_session *se
+ }
+ }
+
+-static void iscsi_start_session_recovery(struct iscsi_session *session,
+- struct iscsi_conn *conn, int flag)
++void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+ {
++ struct iscsi_conn *conn = cls_conn->dd_data;
++ struct iscsi_session *session = conn->session;
+ int old_stop_stage;
+
+ mutex_lock(&session->eh_mutex);
+@@ -3149,27 +3150,6 @@ static void iscsi_start_session_recovery
+ spin_unlock_bh(&session->frwd_lock);
+ mutex_unlock(&session->eh_mutex);
+ }
+-
+-void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+-{
+- struct iscsi_conn *conn = cls_conn->dd_data;
+- struct iscsi_session *session = conn->session;
+-
+- switch (flag) {
+- case STOP_CONN_RECOVER:
+- cls_conn->state = ISCSI_CONN_FAILED;
+- break;
+- case STOP_CONN_TERM:
+- cls_conn->state = ISCSI_CONN_DOWN;
+- break;
+- default:
+- iscsi_conn_printk(KERN_ERR, conn,
+- "invalid stop flag %d\n", flag);
+- return;
+- }
+-
+- iscsi_start_session_recovery(session, conn, flag);
+-}
+ EXPORT_SYMBOL_GPL(iscsi_conn_stop);
+
+ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2479,10 +2479,22 @@ static void iscsi_if_stop_conn(struct is
+ * it works.
+ */
+ mutex_lock(&conn_mutex);
++ switch (flag) {
++ case STOP_CONN_RECOVER:
++ conn->state = ISCSI_CONN_FAILED;
++ break;
++ case STOP_CONN_TERM:
++ conn->state = ISCSI_CONN_DOWN;
++ break;
++ default:
++ iscsi_cls_conn_printk(KERN_ERR, conn,
++ "invalid stop flag %d\n", flag);
++ goto unlock;
++ }
++
+ conn->transport->stop_conn(conn, flag);
+- conn->state = ISCSI_CONN_DOWN;
++unlock:
+ mutex_unlock(&conn_mutex);
+-
+ }
+
+ static void stop_conn_work_fn(struct work_struct *work)
+@@ -2973,7 +2985,7 @@ static int iscsi_if_ep_disconnect(struct
+ mutex_lock(&conn->ep_mutex);
+ conn->ep = NULL;
+ mutex_unlock(&conn->ep_mutex);
+- conn->state = ISCSI_CONN_DOWN;
++ conn->state = ISCSI_CONN_FAILED;
+ }
+
+ transport->ep_disconnect(ep);
--- /dev/null
+From foo@baz Thu Jul 15 01:10:15 PM CEST 2021
+From: Hanjun Guo <guohanjun@huawei.com>
+Date: Tue, 13 Jul 2021 17:18:36 +0800
+Subject: scsi: iscsi: Fix race condition between login and sync thread
+To: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, Gulam Mohamed <gulam.mohamed@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Hanjun Guo <guohanjun@huawei.com>
+Message-ID: <1626167917-11972-7-git-send-email-guohanjun@huawei.com>
+
+From: Gulam Mohamed <gulam.mohamed@oracle.com>
+
+commit 9e67600ed6b8565da4b85698ec659b5879a6c1c6 upstream.
+
+A kernel panic was observed due to a timing issue between the sync thread
+and the initiator processing a login response from the target. The session
+reopen can be invoked both from the session sync thread when iscsid
+restarts and from iscsid through the error handler. Before the initiator
+receives the response to a login, another reopen request can be sent from
+the error handler/sync session. When the initial login response is
+subsequently processed, the connection has been closed and the socket has
+been released.
+
+To fix this a new connection state, ISCSI_CONN_BOUND, is added:
+
+ - Set the connection state value to ISCSI_CONN_DOWN upon
+ iscsi_if_ep_disconnect() and iscsi_if_stop_conn()
+
+ - Set the connection state to the newly created value ISCSI_CONN_BOUND
+ after bind connection (transport->bind_conn())
+
+ - In iscsi_set_param(), return -ENOTCONN if the connection state is not
+ either ISCSI_CONN_BOUND or ISCSI_CONN_UP
+
+Link: https://lore.kernel.org/r/20210325093248.284678-1-gulam.mohamed@oracle.com
+Reviewed-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Gulam Mohamed <gulam.mohamed@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Hanjun Guo <guohanjun@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 14 +++++++++++++-
+ include/scsi/scsi_transport_iscsi.h | 1 +
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2480,6 +2480,7 @@ static void iscsi_if_stop_conn(struct is
+ */
+ mutex_lock(&conn_mutex);
+ conn->transport->stop_conn(conn, flag);
++ conn->state = ISCSI_CONN_DOWN;
+ mutex_unlock(&conn_mutex);
+
+ }
+@@ -2906,6 +2907,13 @@ iscsi_set_param(struct iscsi_transport *
+ default:
+ err = transport->set_param(conn, ev->u.set_param.param,
+ data, ev->u.set_param.len);
++ if ((conn->state == ISCSI_CONN_BOUND) ||
++ (conn->state == ISCSI_CONN_UP)) {
++ err = transport->set_param(conn, ev->u.set_param.param,
++ data, ev->u.set_param.len);
++ } else {
++ return -ENOTCONN;
++ }
+ }
+
+ return err;
+@@ -2965,6 +2973,7 @@ static int iscsi_if_ep_disconnect(struct
+ mutex_lock(&conn->ep_mutex);
+ conn->ep = NULL;
+ mutex_unlock(&conn->ep_mutex);
++ conn->state = ISCSI_CONN_DOWN;
+ }
+
+ transport->ep_disconnect(ep);
+@@ -3732,6 +3741,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, s
+ ev->r.retcode = transport->bind_conn(session, conn,
+ ev->u.b_conn.transport_eph,
+ ev->u.b_conn.is_leading);
++ if (!ev->r.retcode)
++ conn->state = ISCSI_CONN_BOUND;
+ mutex_unlock(&conn_mutex);
+
+ if (ev->r.retcode || !transport->ep_connect)
+@@ -3971,7 +3982,8 @@ iscsi_conn_attr(local_ipaddr, ISCSI_PARA
+ static const char *const connection_state_names[] = {
+ [ISCSI_CONN_UP] = "up",
+ [ISCSI_CONN_DOWN] = "down",
+- [ISCSI_CONN_FAILED] = "failed"
++ [ISCSI_CONN_FAILED] = "failed",
++ [ISCSI_CONN_BOUND] = "bound"
+ };
+
+ static ssize_t show_conn_state(struct device *dev,
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -193,6 +193,7 @@ enum iscsi_connection_state {
+ ISCSI_CONN_UP = 0,
+ ISCSI_CONN_DOWN,
+ ISCSI_CONN_FAILED,
++ ISCSI_CONN_BOUND,
+ };
+
+ struct iscsi_cls_conn {
--- /dev/null
+From 1421ec684a43379b2aa3cfda20b03d38282dc990 Mon Sep 17 00:00:00 2001
+From: Xiaochen Shen <xiaochen.shen@intel.com>
+Date: Thu, 27 May 2021 17:31:53 +0800
+Subject: selftests/resctrl: Fix incorrect parsing of option "-t"
+
+From: Xiaochen Shen <xiaochen.shen@intel.com>
+
+commit 1421ec684a43379b2aa3cfda20b03d38282dc990 upstream.
+
+Resctrl test suite accepts command line argument "-t" to specify the
+unit tests to run in the test list (e.g., -t mbm,mba,cmt,cat) as
+documented in the help.
+
+When calling strtok() to parse the option, the incorrect delimiters
+argument ":\t" is used. As a result, passing "-t mbm,mba,cmt,cat" throws
+an invalid option error.
+
+Fix this by using delimiters argument "," instead of ":\t" for parsing
+of unit tests list. At the same time, remove the unnecessary "spaces"
+between the unit tests in help documentation to prevent confusion.
+
+Fixes: 790bf585b0ee ("selftests/resctrl: Add Cache Allocation Technology (CAT) selftest")
+Fixes: 78941183d1b1 ("selftests/resctrl: Add Cache QoS Monitoring (CQM) selftest")
+Fixes: ecdbb911f22d ("selftests/resctrl: Add MBM test")
+Fixes: 034c7678dd2c ("selftests/resctrl: Add README for resctrl tests")
+Cc: stable@vger.kernel.org
+Signed-off-by: Xiaochen Shen <xiaochen.shen@intel.com>
+Reviewed-by: Tony Luck <tony.luck@intel.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/testing/selftests/resctrl/README | 2 +-
+ tools/testing/selftests/resctrl/resctrl_tests.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/tools/testing/selftests/resctrl/README
++++ b/tools/testing/selftests/resctrl/README
+@@ -47,7 +47,7 @@ Parameter '-h' shows usage information.
+
+ usage: resctrl_tests [-h] [-b "benchmark_cmd [options]"] [-t test list] [-n no_of_bits]
+ -b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CQM default benchmark is builtin fill_buf
+- -t test list: run tests specified in the test list, e.g. -t mbm, mba, cqm, cat
++ -t test list: run tests specified in the test list, e.g. -t mbm,mba,cqm,cat
+ -n no_of_bits: run cache tests using specified no of bits in cache bit mask
+ -p cpu_no: specify CPU number to run the test. 1 is default
+ -h: help
+--- a/tools/testing/selftests/resctrl/resctrl_tests.c
++++ b/tools/testing/selftests/resctrl/resctrl_tests.c
+@@ -40,7 +40,7 @@ static void cmd_help(void)
+ printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CQM");
+ printf("\t default benchmark is builtin fill_buf\n");
+ printf("\t-t test list: run tests specified in the test list, ");
+- printf("e.g. -t mbm, mba, cqm, cat\n");
++ printf("e.g. -t mbm,mba,cqm,cat\n");
+ printf("\t-n no_of_bits: run cache tests using specified no of bits in cache bit mask\n");
+ printf("\t-p cpu_no: specify CPU number to run the test. 1 is default\n");
+ printf("\t-h: help\n");
+@@ -98,7 +98,7 @@ int main(int argc, char **argv)
+
+ return -1;
+ }
+- token = strtok(NULL, ":\t");
++ token = strtok(NULL, ",");
+ }
+ break;
+ case 'p':
sctp-add-size-validation-when-walking-chunks.patch
mips-loongsoon64-reserve-memory-below-starting-pfn-t.patch
mips-set-mips32r5-for-virt-extensions.patch
+selftests-resctrl-fix-incorrect-parsing-of-option-t.patch
+mips-mt-extensions-are-not-available-on-mips32r1.patch
+ath11k-unlock-on-error-path-in-ath11k_mac_op_add_interface.patch
+arm64-dts-rockchip-add-rk3328-dwc3-usb-controller-node.patch
+arm64-dts-rockchip-enable-usb3-for-rk3328-rock64.patch
+mm-page_alloc-fix-memory-map-initialization-for-descending-nodes.patch
+loop-fix-i-o-error-on-fsync-in-detached-loop-devices.patch
+mm-hwpoison-return-ebusy-when-migration-fails.patch
+io_uring-simplify-io_remove_personalities.patch
+io_uring-convert-personality_idr-to-xarray.patch
+io_uring-convert-io_buffer_idr-to-xarray.patch
+scsi-iscsi-fix-race-condition-between-login-and-sync-thread.patch
+scsi-iscsi-fix-iscsi-cls-conn-state.patch