--- /dev/null
+From 4b085736e44dbbe69b5eea1a8a294f404678a1f4 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Thu, 11 Jan 2024 20:51:22 +0900
+Subject: ata: libata-core: Do not try to set sleeping devices to standby
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit 4b085736e44dbbe69b5eea1a8a294f404678a1f4 upstream.
+
+In ata ata_dev_power_set_standby(), check that the target device is not
+sleeping. If it is, there is no need to do anything.
+
+Fixes: aa3998dbeb3a ("ata: libata-scsi: Disable scsi device manage_system_start_stop")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/libata-core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -2005,6 +2005,10 @@ void ata_dev_power_set_active(struct ata
+ struct ata_taskfile tf;
+ unsigned int err_mask;
+
++ /* If the device is already sleeping, do nothing. */
++ if (dev->flags & ATA_DFLAG_SLEEPING)
++ return;
++
+ /*
+ * Issue READ VERIFY SECTORS command for 1 sector at lba=0 only
+ * if supported by the device.
--- /dev/null
+From e21a2f17566cbd64926fb8f16323972f7a064444 Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Sat, 17 Feb 2024 16:14:31 +0800
+Subject: cachefiles: fix memory leak in cachefiles_add_cache()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit e21a2f17566cbd64926fb8f16323972f7a064444 upstream.
+
+The following memory leak was reported after unbinding /dev/cachefiles:
+
+==================================================================
+unreferenced object 0xffff9b674176e3c0 (size 192):
+ comm "cachefilesd2", pid 680, jiffies 4294881224
+ hex dump (first 32 bytes):
+ 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ backtrace (crc ea38a44b):
+ [<ffffffff8eb8a1a5>] kmem_cache_alloc+0x2d5/0x370
+ [<ffffffff8e917f86>] prepare_creds+0x26/0x2e0
+ [<ffffffffc002eeef>] cachefiles_determine_cache_security+0x1f/0x120
+ [<ffffffffc00243ec>] cachefiles_add_cache+0x13c/0x3a0
+ [<ffffffffc0025216>] cachefiles_daemon_write+0x146/0x1c0
+ [<ffffffff8ebc4a3b>] vfs_write+0xcb/0x520
+ [<ffffffff8ebc5069>] ksys_write+0x69/0xf0
+ [<ffffffff8f6d4662>] do_syscall_64+0x72/0x140
+ [<ffffffff8f8000aa>] entry_SYSCALL_64_after_hwframe+0x6e/0x76
+==================================================================
+
+Put the reference count of cache_cred in cachefiles_daemon_unbind() to
+fix the problem. And also put cache_cred in cachefiles_add_cache() error
+branch to avoid memory leaks.
+
+Fixes: 9ae326a69004 ("CacheFiles: A cache that backs onto a mounted filesystem")
+CC: stable@vger.kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Link: https://lore.kernel.org/r/20240217081431.796809-1-libaokun1@huawei.com
+Acked-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cachefiles/cache.c | 2 ++
+ fs/cachefiles/daemon.c | 1 +
+ 2 files changed, 3 insertions(+)
+
+--- a/fs/cachefiles/cache.c
++++ b/fs/cachefiles/cache.c
+@@ -168,6 +168,8 @@ error_unsupported:
+ dput(root);
+ error_open_root:
+ cachefiles_end_secure(cache, saved_cred);
++ put_cred(cache->cache_cred);
++ cache->cache_cred = NULL;
+ error_getsec:
+ fscache_relinquish_cache(cache_cookie);
+ cache->cache = NULL;
+--- a/fs/cachefiles/daemon.c
++++ b/fs/cachefiles/daemon.c
+@@ -805,6 +805,7 @@ static void cachefiles_daemon_unbind(str
+ cachefiles_put_directory(cache->graveyard);
+ cachefiles_put_directory(cache->store);
+ mntput(cache->mnt);
++ put_cred(cache->cache_cred);
+
+ kfree(cache->rootdirname);
+ kfree(cache->secctx);
--- /dev/null
+From c0ec2a712daf133d9996a8a1b7ee2d4996080363 Mon Sep 17 00:00:00 2001
+From: zhenwei pi <pizhenwei@bytedance.com>
+Date: Tue, 30 Jan 2024 19:27:40 +0800
+Subject: crypto: virtio/akcipher - Fix stack overflow on memcpy
+
+From: zhenwei pi <pizhenwei@bytedance.com>
+
+commit c0ec2a712daf133d9996a8a1b7ee2d4996080363 upstream.
+
+sizeof(struct virtio_crypto_akcipher_session_para) is less than
+sizeof(struct virtio_crypto_op_ctrl_req::u), copying more bytes from
+stack variable leads stack overflow. Clang reports this issue by
+commands:
+make -j CC=clang-14 mrproper >/dev/null 2>&1
+make -j O=/tmp/crypto-build CC=clang-14 allmodconfig >/dev/null 2>&1
+make -j O=/tmp/crypto-build W=1 CC=clang-14 drivers/crypto/virtio/
+ virtio_crypto_akcipher_algs.o
+
+Fixes: 59ca6c93387d ("virtio-crypto: implement RSA algorithm")
+Link: https://lore.kernel.org/all/0a194a79-e3a3-45e7-be98-83abd3e1cb7e@roeck-us.net/
+Cc: <stable@vger.kernel.org>
+Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
+Tested-by: Nathan Chancellor <nathan@kernel.org> # build
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/virtio/virtio_crypto_akcipher_algs.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
++++ b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
+@@ -104,7 +104,8 @@ static void virtio_crypto_dataq_akcipher
+ }
+
+ static int virtio_crypto_alg_akcipher_init_session(struct virtio_crypto_akcipher_ctx *ctx,
+- struct virtio_crypto_ctrl_header *header, void *para,
++ struct virtio_crypto_ctrl_header *header,
++ struct virtio_crypto_akcipher_session_para *para,
+ const uint8_t *key, unsigned int keylen)
+ {
+ struct scatterlist outhdr_sg, key_sg, inhdr_sg, *sgs[3];
+@@ -128,7 +129,7 @@ static int virtio_crypto_alg_akcipher_in
+
+ ctrl = &vc_ctrl_req->ctrl;
+ memcpy(&ctrl->header, header, sizeof(ctrl->header));
+- memcpy(&ctrl->u, para, sizeof(ctrl->u));
++ memcpy(&ctrl->u.akcipher_create_session.para, para, sizeof(*para));
+ input = &vc_ctrl_req->input;
+ input->status = cpu_to_le32(VIRTIO_CRYPTO_ERR);
+
--- /dev/null
+From 0cab687205986491302cd2e440ef1d253031c221 Mon Sep 17 00:00:00 2001
+From: Robert Richter <rrichter@amd.com>
+Date: Fri, 16 Feb 2024 17:01:13 +0100
+Subject: cxl/pci: Fix disabling memory if DVSEC CXL Range does not match a CFMWS window
+
+From: Robert Richter <rrichter@amd.com>
+
+commit 0cab687205986491302cd2e440ef1d253031c221 upstream.
+
+The Linux CXL subsystem is built on the assumption that HPA == SPA.
+That is, the host physical address (HPA) the HDM decoder registers are
+programmed with are system physical addresses (SPA).
+
+During HDM decoder setup, the DVSEC CXL range registers (cxl-3.1,
+8.1.3.8) are checked if the memory is enabled and the CXL range is in
+a HPA window that is described in a CFMWS structure of the CXL host
+bridge (cxl-3.1, 9.18.1.3).
+
+Now, if the HPA is not an SPA, the CXL range does not match a CFMWS
+window and the CXL memory range will be disabled then. The HDM decoder
+stops working which causes system memory being disabled and further a
+system hang during HDM decoder initialization, typically when a CXL
+enabled kernel boots.
+
+Prevent a system hang and do not disable the HDM decoder if the
+decoder's CXL range is not found in a CFMWS window.
+
+Note the change only fixes a hardware hang, but does not implement
+HPA/SPA translation. Support for this can be added in a follow on
+patch series.
+
+Signed-off-by: Robert Richter <rrichter@amd.com>
+Fixes: 34e37b4c432c ("cxl/port: Enable HDM Capability after validating DVSEC Ranges")
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20240216160113.407141-1-rrichter@amd.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cxl/core/pci.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/cxl/core/pci.c
++++ b/drivers/cxl/core/pci.c
+@@ -376,9 +376,9 @@ static bool __cxl_hdm_decode_init(struct
+ allowed++;
+ }
+
+- if (!allowed) {
+- cxl_set_mem_enable(cxlds, 0);
+- info->mem_enabled = 0;
++ if (!allowed && info->mem_enabled) {
++ dev_err(dev, "Range register decodes outside platform defined CXL ranges.\n");
++ return -ENXIO;
+ }
+
+ /*
--- /dev/null
+From 50c70240097ce41fe6bce6478b80478281e4d0f7 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 19 Feb 2024 21:30:10 +0100
+Subject: dm-crypt: don't modify the data when using authenticated encryption
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 50c70240097ce41fe6bce6478b80478281e4d0f7 upstream.
+
+It was said that authenticated encryption could produce invalid tag when
+the data that is being encrypted is modified [1]. So, fix this problem by
+copying the data into the clone bio first and then encrypt them inside the
+clone bio.
+
+This may reduce performance, but it is needed to prevent the user from
+corrupting the device by writing data with O_DIRECT and modifying them at
+the same time.
+
+[1] https://lore.kernel.org/all/20240207004723.GA35324@sol.localdomain/T/
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-crypt.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -2078,6 +2078,12 @@ static void kcryptd_crypt_write_convert(
+ io->ctx.bio_out = clone;
+ io->ctx.iter_out = clone->bi_iter;
+
++ if (crypt_integrity_aead(cc)) {
++ bio_copy_data(clone, io->base_bio);
++ io->ctx.bio_in = clone;
++ io->ctx.iter_in = clone->bi_iter;
++ }
++
+ sector += bio_sectors(clone);
+
+ crypt_inc_pending(io);
--- /dev/null
+From 42e15d12070b4ff9af2b980f1b65774c2dab0507 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 19 Feb 2024 21:31:11 +0100
+Subject: dm-crypt: recheck the integrity tag after a failure
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 42e15d12070b4ff9af2b980f1b65774c2dab0507 upstream.
+
+If a userspace process reads (with O_DIRECT) multiple blocks into the same
+buffer, dm-crypt reports an authentication error [1]. The error is
+reported in a log and it may cause RAID leg being kicked out of the
+array.
+
+This commit fixes dm-crypt, so that if integrity verification fails, the
+data is read again into a kernel buffer (where userspace can't modify it)
+and the integrity tag is rechecked. If the recheck succeeds, the content
+of the kernel buffer is copied into the user buffer; if the recheck fails,
+an integrity error is reported.
+
+[1] https://people.redhat.com/~mpatocka/testcases/blk-auth-modify/read2.c
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-crypt.c | 89 +++++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 73 insertions(+), 16 deletions(-)
+
+--- a/drivers/md/dm-crypt.c
++++ b/drivers/md/dm-crypt.c
+@@ -61,6 +61,8 @@ struct convert_context {
+ struct skcipher_request *req;
+ struct aead_request *req_aead;
+ } r;
++ bool aead_recheck;
++ bool aead_failed;
+
+ };
+
+@@ -81,6 +83,8 @@ struct dm_crypt_io {
+ blk_status_t error;
+ sector_t sector;
+
++ struct bvec_iter saved_bi_iter;
++
+ struct rb_node rb_node;
+ } CRYPTO_MINALIGN_ATTR;
+
+@@ -1365,10 +1369,13 @@ static int crypt_convert_block_aead(stru
+ if (r == -EBADMSG) {
+ sector_t s = le64_to_cpu(*sector);
+
+- DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu",
+- ctx->bio_in->bi_bdev, s);
+- dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead",
+- ctx->bio_in, s, 0);
++ ctx->aead_failed = true;
++ if (ctx->aead_recheck) {
++ DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu",
++ ctx->bio_in->bi_bdev, s);
++ dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead",
++ ctx->bio_in, s, 0);
++ }
+ }
+
+ if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post)
+@@ -1724,6 +1731,8 @@ static void crypt_io_init(struct dm_cryp
+ io->base_bio = bio;
+ io->sector = sector;
+ io->error = 0;
++ io->ctx.aead_recheck = false;
++ io->ctx.aead_failed = false;
+ io->ctx.r.req = NULL;
+ io->integrity_metadata = NULL;
+ io->integrity_metadata_from_pool = false;
+@@ -1735,6 +1744,8 @@ static void crypt_inc_pending(struct dm_
+ atomic_inc(&io->io_pending);
+ }
+
++static void kcryptd_queue_read(struct dm_crypt_io *io);
++
+ /*
+ * One of the bios was finished. Check for completion of
+ * the whole request and correctly clean up the buffer.
+@@ -1748,6 +1759,15 @@ static void crypt_dec_pending(struct dm_
+ if (!atomic_dec_and_test(&io->io_pending))
+ return;
+
++ if (likely(!io->ctx.aead_recheck) && unlikely(io->ctx.aead_failed) &&
++ cc->on_disk_tag_size && bio_data_dir(base_bio) == READ) {
++ io->ctx.aead_recheck = true;
++ io->ctx.aead_failed = false;
++ io->error = 0;
++ kcryptd_queue_read(io);
++ return;
++ }
++
+ if (io->ctx.r.req)
+ crypt_free_req(cc, io->ctx.r.req, base_bio);
+
+@@ -1783,15 +1803,19 @@ static void crypt_endio(struct bio *clon
+ struct dm_crypt_io *io = clone->bi_private;
+ struct crypt_config *cc = io->cc;
+ unsigned int rw = bio_data_dir(clone);
+- blk_status_t error;
++ blk_status_t error = clone->bi_status;
++
++ if (io->ctx.aead_recheck && !error) {
++ kcryptd_queue_crypt(io);
++ return;
++ }
+
+ /*
+ * free the processed pages
+ */
+- if (rw == WRITE)
++ if (rw == WRITE || io->ctx.aead_recheck)
+ crypt_free_buffer_pages(cc, clone);
+
+- error = clone->bi_status;
+ bio_put(clone);
+
+ if (rw == READ && !error) {
+@@ -1812,6 +1836,22 @@ static int kcryptd_io_read(struct dm_cry
+ struct crypt_config *cc = io->cc;
+ struct bio *clone;
+
++ if (io->ctx.aead_recheck) {
++ if (!(gfp & __GFP_DIRECT_RECLAIM))
++ return 1;
++ crypt_inc_pending(io);
++ clone = crypt_alloc_buffer(io, io->base_bio->bi_iter.bi_size);
++ if (unlikely(!clone)) {
++ crypt_dec_pending(io);
++ return 1;
++ }
++ clone->bi_iter.bi_sector = cc->start + io->sector;
++ crypt_convert_init(cc, &io->ctx, clone, clone, io->sector);
++ io->saved_bi_iter = clone->bi_iter;
++ dm_submit_bio_remap(io->base_bio, clone);
++ return 0;
++ }
++
+ /*
+ * We need the original biovec array in order to decrypt the whole bio
+ * data *afterwards* -- thanks to immutable biovecs we don't need to
+@@ -2074,6 +2114,14 @@ dec:
+
+ static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
+ {
++ if (io->ctx.aead_recheck) {
++ if (!io->error) {
++ io->ctx.bio_in->bi_iter = io->saved_bi_iter;
++ bio_copy_data(io->base_bio, io->ctx.bio_in);
++ }
++ crypt_free_buffer_pages(io->cc, io->ctx.bio_in);
++ bio_put(io->ctx.bio_in);
++ }
+ crypt_dec_pending(io);
+ }
+
+@@ -2103,11 +2151,17 @@ static void kcryptd_crypt_read_convert(s
+
+ crypt_inc_pending(io);
+
+- crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio,
+- io->sector);
++ if (io->ctx.aead_recheck) {
++ io->ctx.cc_sector = io->sector + cc->iv_offset;
++ r = crypt_convert(cc, &io->ctx,
++ test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true);
++ } else {
++ crypt_convert_init(cc, &io->ctx, io->base_bio, io->base_bio,
++ io->sector);
+
+- r = crypt_convert(cc, &io->ctx,
+- test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true);
++ r = crypt_convert(cc, &io->ctx,
++ test_bit(DM_CRYPT_NO_READ_WORKQUEUE, &cc->flags), true);
++ }
+ /*
+ * Crypto API backlogged the request, because its queue was full
+ * and we're in softirq context, so continue from a workqueue
+@@ -2150,10 +2204,13 @@ static void kcryptd_async_done(struct cr
+ if (error == -EBADMSG) {
+ sector_t s = le64_to_cpu(*org_sector_of_dmreq(cc, dmreq));
+
+- DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu",
+- ctx->bio_in->bi_bdev, s);
+- dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead",
+- ctx->bio_in, s, 0);
++ ctx->aead_failed = true;
++ if (ctx->aead_recheck) {
++ DMERR_LIMIT("%pg: INTEGRITY AEAD ERROR, sector %llu",
++ ctx->bio_in->bi_bdev, s);
++ dm_audit_log_bio(DM_MSG_PREFIX, "integrity-aead",
++ ctx->bio_in, s, 0);
++ }
+ io->error = BLK_STS_PROTECTION;
+ } else if (error < 0)
+ io->error = BLK_STS_IOERR;
+@@ -3079,7 +3136,7 @@ static int crypt_ctr_optional(struct dm_
+ sval = strchr(opt_string + strlen("integrity:"), ':') + 1;
+ if (!strcasecmp(sval, "aead")) {
+ set_bit(CRYPT_MODE_INTEGRITY_AEAD, &cc->cipher_flags);
+- } else if (strcasecmp(sval, "none")) {
++ } else if (strcasecmp(sval, "none")) {
+ ti->error = "Unknown integrity profile";
+ return -EINVAL;
+ }
--- /dev/null
+From c88f5e553fe38b2ffc4c33d08654e5281b297677 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 19 Feb 2024 21:27:39 +0100
+Subject: dm-integrity: recheck the integrity tag after a failure
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit c88f5e553fe38b2ffc4c33d08654e5281b297677 upstream.
+
+If a userspace process reads (with O_DIRECT) multiple blocks into the same
+buffer, dm-integrity reports an error [1]. The error is reported in a log
+and it may cause RAID leg being kicked out of the array.
+
+This commit fixes dm-integrity, so that if integrity verification fails,
+the data is read again into a kernel buffer (where userspace can't modify
+it) and the integrity tag is rechecked. If the recheck succeeds, the
+content of the kernel buffer is copied into the user buffer; if the
+recheck fails, an integrity error is reported.
+
+[1] https://people.redhat.com/~mpatocka/testcases/blk-auth-modify/read2.c
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-integrity.c | 93 +++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 84 insertions(+), 9 deletions(-)
+
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -279,6 +279,8 @@ struct dm_integrity_c {
+
+ atomic64_t number_of_mismatches;
+
++ mempool_t recheck_pool;
++
+ struct notifier_block reboot_notifier;
+ };
+
+@@ -1699,6 +1701,79 @@ failed:
+ get_random_bytes(result, ic->tag_size);
+ }
+
++static void integrity_recheck(struct dm_integrity_io *dio)
++{
++ struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
++ struct dm_integrity_c *ic = dio->ic;
++ struct bvec_iter iter;
++ struct bio_vec bv;
++ sector_t sector, logical_sector, area, offset;
++ char checksum_onstack[max_t(size_t, HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
++ struct page *page;
++ void *buffer;
++
++ get_area_and_offset(ic, dio->range.logical_sector, &area, &offset);
++ dio->metadata_block = get_metadata_sector_and_offset(ic, area, offset,
++ &dio->metadata_offset);
++ sector = get_data_sector(ic, area, offset);
++ logical_sector = dio->range.logical_sector;
++
++ page = mempool_alloc(&ic->recheck_pool, GFP_NOIO);
++ buffer = page_to_virt(page);
++
++ __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
++ unsigned pos = 0;
++
++ do {
++ char *mem;
++ int r;
++ struct dm_io_request io_req;
++ struct dm_io_region io_loc;
++ io_req.bi_opf = REQ_OP_READ;
++ io_req.mem.type = DM_IO_KMEM;
++ io_req.mem.ptr.addr = buffer;
++ io_req.notify.fn = NULL;
++ io_req.client = ic->io;
++ io_loc.bdev = ic->dev->bdev;
++ io_loc.sector = sector;
++ io_loc.count = ic->sectors_per_block;
++
++ r = dm_io(&io_req, 1, &io_loc, NULL);
++ if (unlikely(r)) {
++ dio->bi_status = errno_to_blk_status(r);
++ goto free_ret;
++ }
++
++ integrity_sector_checksum(ic, logical_sector, buffer,
++ checksum_onstack);
++ r = dm_integrity_rw_tag(ic, checksum_onstack, &dio->metadata_block,
++ &dio->metadata_offset, ic->tag_size, TAG_CMP);
++ if (r) {
++ if (r > 0) {
++ DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx",
++ bio->bi_bdev, logical_sector);
++ atomic64_inc(&ic->number_of_mismatches);
++ dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum",
++ bio, logical_sector, 0);
++ r = -EILSEQ;
++ }
++ dio->bi_status = errno_to_blk_status(r);
++ goto free_ret;
++ }
++
++ mem = bvec_kmap_local(&bv);
++ memcpy(mem + pos, buffer, ic->sectors_per_block << SECTOR_SHIFT);
++ kunmap_local(mem);
++
++ pos += ic->sectors_per_block << SECTOR_SHIFT;
++ sector += ic->sectors_per_block;
++ logical_sector += ic->sectors_per_block;
++ } while (pos < bv.bv_len);
++ }
++free_ret:
++ mempool_free(page, &ic->recheck_pool);
++}
++
+ static void integrity_metadata(struct work_struct *w)
+ {
+ struct dm_integrity_io *dio = container_of(w, struct dm_integrity_io, work);
+@@ -1784,15 +1859,8 @@ again:
+ checksums_ptr - checksums, dio->op == REQ_OP_READ ? TAG_CMP : TAG_WRITE);
+ if (unlikely(r)) {
+ if (r > 0) {
+- sector_t s;
+-
+- s = sector - ((r + ic->tag_size - 1) / ic->tag_size);
+- DMERR_LIMIT("%pg: Checksum failed at sector 0x%llx",
+- bio->bi_bdev, s);
+- r = -EILSEQ;
+- atomic64_inc(&ic->number_of_mismatches);
+- dm_audit_log_bio(DM_MSG_PREFIX, "integrity-checksum",
+- bio, s, 0);
++ integrity_recheck(dio);
++ goto skip_io;
+ }
+ if (likely(checksums != checksums_onstack))
+ kfree(checksums);
+@@ -4208,6 +4276,12 @@ static int dm_integrity_ctr(struct dm_ta
+ goto bad;
+ }
+
++ r = mempool_init_page_pool(&ic->recheck_pool, 1, 0);
++ if (r) {
++ ti->error = "Cannot allocate mempool";
++ goto bad;
++ }
++
+ ic->metadata_wq = alloc_workqueue("dm-integrity-metadata",
+ WQ_MEM_RECLAIM, METADATA_WORKQUEUE_MAX_ACTIVE);
+ if (!ic->metadata_wq) {
+@@ -4572,6 +4646,7 @@ static void dm_integrity_dtr(struct dm_t
+ kvfree(ic->bbs);
+ if (ic->bufio)
+ dm_bufio_client_destroy(ic->bufio);
++ mempool_exit(&ic->recheck_pool);
+ mempool_exit(&ic->journal_io_mempool);
+ if (ic->io)
+ dm_io_client_destroy(ic->io);
--- /dev/null
+From 9177f3c0dea6143d05cac1bbd28668fd0e216d11 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Mon, 19 Feb 2024 21:28:09 +0100
+Subject: dm-verity: recheck the hash after a failure
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 9177f3c0dea6143d05cac1bbd28668fd0e216d11 upstream.
+
+If a userspace process reads (with O_DIRECT) multiple blocks into the same
+buffer, dm-verity reports an error [1].
+
+This commit fixes dm-verity, so that if hash verification fails, the data
+is read again into a kernel buffer (where userspace can't modify it) and
+the hash is rechecked. If the recheck succeeds, the content of the kernel
+buffer is copied into the user buffer; if the recheck fails, an error is
+reported.
+
+[1] https://people.redhat.com/~mpatocka/testcases/blk-auth-modify/read2.c
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-verity-target.c | 86 +++++++++++++++++++++++++++++++++++++++---
+ drivers/md/dm-verity.h | 6 ++
+ 2 files changed, 86 insertions(+), 6 deletions(-)
+
+--- a/drivers/md/dm-verity-target.c
++++ b/drivers/md/dm-verity-target.c
+@@ -474,6 +474,63 @@ int verity_for_bv_block(struct dm_verity
+ return 0;
+ }
+
++static int verity_recheck_copy(struct dm_verity *v, struct dm_verity_io *io,
++ u8 *data, size_t len)
++{
++ memcpy(data, io->recheck_buffer, len);
++ io->recheck_buffer += len;
++
++ return 0;
++}
++
++static int verity_recheck(struct dm_verity *v, struct dm_verity_io *io,
++ struct bvec_iter start, sector_t cur_block)
++{
++ struct page *page;
++ void *buffer;
++ int r;
++ struct dm_io_request io_req;
++ struct dm_io_region io_loc;
++
++ page = mempool_alloc(&v->recheck_pool, GFP_NOIO);
++ buffer = page_to_virt(page);
++
++ io_req.bi_opf = REQ_OP_READ;
++ io_req.mem.type = DM_IO_KMEM;
++ io_req.mem.ptr.addr = buffer;
++ io_req.notify.fn = NULL;
++ io_req.client = v->io;
++ io_loc.bdev = v->data_dev->bdev;
++ io_loc.sector = cur_block << (v->data_dev_block_bits - SECTOR_SHIFT);
++ io_loc.count = 1 << (v->data_dev_block_bits - SECTOR_SHIFT);
++ r = dm_io(&io_req, 1, &io_loc, NULL);
++ if (unlikely(r))
++ goto free_ret;
++
++ r = verity_hash(v, verity_io_hash_req(v, io), buffer,
++ 1 << v->data_dev_block_bits,
++ verity_io_real_digest(v, io), true);
++ if (unlikely(r))
++ goto free_ret;
++
++ if (memcmp(verity_io_real_digest(v, io),
++ verity_io_want_digest(v, io), v->digest_size)) {
++ r = -EIO;
++ goto free_ret;
++ }
++
++ io->recheck_buffer = buffer;
++ r = verity_for_bv_block(v, io, &start, verity_recheck_copy);
++ if (unlikely(r))
++ goto free_ret;
++
++ r = 0;
++free_ret:
++ mempool_free(page, &v->recheck_pool);
++
++ return r;
++}
++
+ static int verity_bv_zero(struct dm_verity *v, struct dm_verity_io *io,
+ u8 *data, size_t len)
+ {
+@@ -500,9 +557,7 @@ static int verity_verify_io(struct dm_ve
+ {
+ bool is_zero;
+ struct dm_verity *v = io->v;
+-#if defined(CONFIG_DM_VERITY_FEC)
+ struct bvec_iter start;
+-#endif
+ struct bvec_iter iter_copy;
+ struct bvec_iter *iter;
+ struct crypto_wait wait;
+@@ -553,10 +608,7 @@ static int verity_verify_io(struct dm_ve
+ if (unlikely(r < 0))
+ return r;
+
+-#if defined(CONFIG_DM_VERITY_FEC)
+- if (verity_fec_is_enabled(v))
+- start = *iter;
+-#endif
++ start = *iter;
+ r = verity_for_io_block(v, io, iter, &wait);
+ if (unlikely(r < 0))
+ return r;
+@@ -578,6 +630,10 @@ static int verity_verify_io(struct dm_ve
+ * tasklet since it may sleep, so fallback to work-queue.
+ */
+ return -EAGAIN;
++ } else if (verity_recheck(v, io, start, cur_block) == 0) {
++ if (v->validated_blocks)
++ set_bit(cur_block, v->validated_blocks);
++ continue;
+ #if defined(CONFIG_DM_VERITY_FEC)
+ } else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA,
+ cur_block, NULL, &start) == 0) {
+@@ -928,6 +984,10 @@ static void verity_dtr(struct dm_target
+ if (v->verify_wq)
+ destroy_workqueue(v->verify_wq);
+
++ mempool_exit(&v->recheck_pool);
++ if (v->io)
++ dm_io_client_destroy(v->io);
++
+ if (v->bufio)
+ dm_bufio_client_destroy(v->bufio);
+
+@@ -1364,6 +1424,20 @@ static int verity_ctr(struct dm_target *
+ }
+ v->hash_blocks = hash_position;
+
++ r = mempool_init_page_pool(&v->recheck_pool, 1, 0);
++ if (unlikely(r)) {
++ ti->error = "Cannot allocate mempool";
++ goto bad;
++ }
++
++ v->io = dm_io_client_create();
++ if (IS_ERR(v->io)) {
++ r = PTR_ERR(v->io);
++ v->io = NULL;
++ ti->error = "Cannot allocate dm io";
++ goto bad;
++ }
++
+ v->bufio = dm_bufio_client_create(v->hash_dev->bdev,
+ 1 << v->hash_dev_block_bits, 1, sizeof(struct buffer_aux),
+ dm_bufio_alloc_callback, NULL,
+--- a/drivers/md/dm-verity.h
++++ b/drivers/md/dm-verity.h
+@@ -11,6 +11,7 @@
+ #ifndef DM_VERITY_H
+ #define DM_VERITY_H
+
++#include <linux/dm-io.h>
+ #include <linux/dm-bufio.h>
+ #include <linux/device-mapper.h>
+ #include <linux/interrupt.h>
+@@ -68,6 +69,9 @@ struct dm_verity {
+ unsigned long *validated_blocks; /* bitset blocks validated */
+
+ char *signature_key_desc; /* signature keyring reference */
++
++ struct dm_io_client *io;
++ mempool_t recheck_pool;
+ };
+
+ struct dm_verity_io {
+@@ -84,6 +88,8 @@ struct dm_verity_io {
+
+ struct work_struct work;
+
++ char *recheck_buffer;
++
+ /*
+ * Three variably-size fields follow this struct:
+ *
--- /dev/null
+From 40510a941d27d405a82dc3320823d875f94625df Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= <thomas.hellstrom@linux.intel.com>
+Date: Wed, 21 Feb 2024 08:33:24 +0100
+Subject: drm/ttm: Fix an invalid freeing on already freed page in error path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+commit 40510a941d27d405a82dc3320823d875f94625df upstream.
+
+If caching mode change fails due to, for example, OOM we
+free the allocated pages in a two-step process. First the pages
+for which the caching change has already succeeded. Secondly
+the pages for which a caching change did not succeed.
+
+However the second step was incorrectly freeing the pages already
+freed in the first step.
+
+Fix.
+
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Fixes: 379989e7cbdc ("drm/ttm/pool: Fix ttm_pool_alloc error path")
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Dave Airlie <airlied@redhat.com>
+Cc: Christian Koenig <christian.koenig@amd.com>
+Cc: Huang Rui <ray.huang@amd.com>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v6.4+
+Reviewed-by: Matthew Auld <matthew.auld@intel.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240221073324.3303-1-thomas.hellstrom@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/ttm/ttm_pool.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/ttm/ttm_pool.c
++++ b/drivers/gpu/drm/ttm/ttm_pool.c
+@@ -383,7 +383,7 @@ static void ttm_pool_free_range(struct t
+ enum ttm_caching caching,
+ pgoff_t start_page, pgoff_t end_page)
+ {
+- struct page **pages = tt->pages;
++ struct page **pages = &tt->pages[start_page];
+ unsigned int order;
+ pgoff_t i, nr;
+
--- /dev/null
+From 136cfaca22567a03bbb3bf53a43d8cb5748b80ec Mon Sep 17 00:00:00 2001
+From: Vasiliy Kovalev <kovalev@altlinux.org>
+Date: Wed, 14 Feb 2024 19:27:33 +0300
+Subject: gtp: fix use-after-free and null-ptr-deref in gtp_genl_dump_pdp()
+
+From: Vasiliy Kovalev <kovalev@altlinux.org>
+
+commit 136cfaca22567a03bbb3bf53a43d8cb5748b80ec upstream.
+
+The gtp_net_ops pernet operations structure for the subsystem must be
+registered before registering the generic netlink family.
+
+Syzkaller hit 'general protection fault in gtp_genl_dump_pdp' bug:
+
+general protection fault, probably for non-canonical address
+0xdffffc0000000002: 0000 [#1] PREEMPT SMP KASAN NOPTI
+KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
+CPU: 1 PID: 5826 Comm: gtp Not tainted 6.8.0-rc3-std-def-alt1 #1
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.0-alt1 04/01/2014
+RIP: 0010:gtp_genl_dump_pdp+0x1be/0x800 [gtp]
+Code: c6 89 c6 e8 64 e9 86 df 58 45 85 f6 0f 85 4e 04 00 00 e8 c5 ee 86
+ df 48 8b 54 24 18 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80>
+ 3c 02 00 0f 85 de 05 00 00 48 8b 44 24 18 4c 8b 30 4c 39 f0 74
+RSP: 0018:ffff888014107220 EFLAGS: 00010202
+RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
+RDX: 0000000000000002 RSI: 0000000000000000 RDI: 0000000000000000
+RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
+R13: ffff88800fcda588 R14: 0000000000000001 R15: 0000000000000000
+FS: 00007f1be4eb05c0(0000) GS:ffff88806ce80000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f1be4e766cf CR3: 000000000c33e000 CR4: 0000000000750ef0
+PKRU: 55555554
+Call Trace:
+ <TASK>
+ ? show_regs+0x90/0xa0
+ ? die_addr+0x50/0xd0
+ ? exc_general_protection+0x148/0x220
+ ? asm_exc_general_protection+0x22/0x30
+ ? gtp_genl_dump_pdp+0x1be/0x800 [gtp]
+ ? __alloc_skb+0x1dd/0x350
+ ? __pfx___alloc_skb+0x10/0x10
+ genl_dumpit+0x11d/0x230
+ netlink_dump+0x5b9/0xce0
+ ? lockdep_hardirqs_on_prepare+0x253/0x430
+ ? __pfx_netlink_dump+0x10/0x10
+ ? kasan_save_track+0x10/0x40
+ ? __kasan_kmalloc+0x9b/0xa0
+ ? genl_start+0x675/0x970
+ __netlink_dump_start+0x6fc/0x9f0
+ genl_family_rcv_msg_dumpit+0x1bb/0x2d0
+ ? __pfx_genl_family_rcv_msg_dumpit+0x10/0x10
+ ? genl_op_from_small+0x2a/0x440
+ ? cap_capable+0x1d0/0x240
+ ? __pfx_genl_start+0x10/0x10
+ ? __pfx_genl_dumpit+0x10/0x10
+ ? __pfx_genl_done+0x10/0x10
+ ? security_capable+0x9d/0xe0
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)")
+Link: https://lore.kernel.org/r/20240214162733.34214-1-kovalev@altlinux.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/gtp.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1906,20 +1906,20 @@ static int __init gtp_init(void)
+ if (err < 0)
+ goto error_out;
+
+- err = genl_register_family(>p_genl_family);
++ err = register_pernet_subsys(>p_net_ops);
+ if (err < 0)
+ goto unreg_rtnl_link;
+
+- err = register_pernet_subsys(>p_net_ops);
++ err = genl_register_family(>p_genl_family);
+ if (err < 0)
+- goto unreg_genl_family;
++ goto unreg_pernet_subsys;
+
+ pr_info("GTP module loaded (pdp ctx size %zd bytes)\n",
+ sizeof(struct pdp_ctx));
+ return 0;
+
+-unreg_genl_family:
+- genl_unregister_family(>p_genl_family);
++unreg_pernet_subsys:
++ unregister_pernet_subsys(>p_net_ops);
+ unreg_rtnl_link:
+ rtnl_link_unregister(>p_link_ops);
+ error_out:
--- /dev/null
+From ec4308ecfc887128a468f03fb66b767559c57c23 Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Mon, 19 Feb 2024 18:58:06 +0000
+Subject: irqchip/gic-v3-its: Do not assume vPE tables are preallocated
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit ec4308ecfc887128a468f03fb66b767559c57c23 upstream.
+
+The GIC/ITS code is designed to ensure to pick up any preallocated LPI
+tables on the redistributors, as enabling LPIs is a one-way switch. There
+is no such restriction for vLPIs, and for GICv4.1 it is expected to
+allocate a new vPE table at boot.
+
+This works as intended when initializing an ITS, however when setting up a
+redistributor in cpu_init_lpis() the early return for preallocated RD
+tables skips straight past the GICv4 setup. This all comes to a head when
+trying to kexec() into a new kernel, as the new kernel silently fails to
+set up GICv4, leading to a complete loss of SGIs and LPIs for KVM VMs.
+
+Slap a band-aid on the problem by ensuring its_cpu_init_lpis() always
+initializes GICv4 on the way out, even if the other RD tables were
+preallocated.
+
+Fixes: 6479450f72c1 ("irqchip/gic-v4: Fix occasional VLPI drop")
+Reported-by: George Cherian <gcherian@marvell.com>
+Co-developed-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240219185809.286724-2-oliver.upton@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-gic-v3-its.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/irqchip/irq-gic-v3-its.c
++++ b/drivers/irqchip/irq-gic-v3-its.c
+@@ -3161,6 +3161,7 @@ static void its_cpu_init_lpis(void)
+ val |= GICR_CTLR_ENABLE_LPIS;
+ writel_relaxed(val, rbase + GICR_CTLR);
+
++out:
+ if (gic_rdists->has_vlpis && !gic_rdists->has_rvpeid) {
+ void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+
+@@ -3196,7 +3197,6 @@ static void its_cpu_init_lpis(void)
+
+ /* Make sure the GIC has seen the above */
+ dsb(sy);
+-out:
+ gic_data_rdist()->flags |= RD_LOCAL_LPI_ENABLED;
+ pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n",
+ smp_processor_id(),
--- /dev/null
+From 9c92006b896c767218aabe8947b62026a571cfd0 Mon Sep 17 00:00:00 2001
+From: Nam Cao <namcao@linutronix.de>
+Date: Wed, 31 Jan 2024 09:19:33 +0100
+Subject: irqchip/sifive-plic: Enable interrupt if needed before EOI
+
+From: Nam Cao <namcao@linutronix.de>
+
+commit 9c92006b896c767218aabe8947b62026a571cfd0 upstream.
+
+RISC-V PLIC cannot "end-of-interrupt" (EOI) disabled interrupts, as
+explained in the description of Interrupt Completion in the PLIC spec:
+
+"The PLIC signals it has completed executing an interrupt handler by
+writing the interrupt ID it received from the claim to the claim/complete
+register. The PLIC does not check whether the completion ID is the same
+as the last claim ID for that target. If the completion ID does not match
+an interrupt source that *is currently enabled* for the target, the
+completion is silently ignored."
+
+Commit 69ea463021be ("irqchip/sifive-plic: Fixup EOI failed when masked")
+ensured that EOI is successful by enabling interrupt first, before EOI.
+
+Commit a1706a1c5062 ("irqchip/sifive-plic: Separate the enable and mask
+operations") removed the interrupt enabling code from the previous
+commit, because it assumes that interrupt should already be enabled at the
+point of EOI.
+
+However, this is incorrect: there is a window after a hart claiming an
+interrupt and before irq_desc->lock getting acquired, interrupt can be
+disabled during this window. Thus, EOI can be invoked while the interrupt
+is disabled, effectively nullify this EOI. This results in the interrupt
+never gets asserted again, and the device who uses this interrupt appears
+frozen.
+
+Make sure that interrupt is really enabled before EOI.
+
+Fixes: a1706a1c5062 ("irqchip/sifive-plic: Separate the enable and mask operations")
+Signed-off-by: Nam Cao <namcao@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Palmer Dabbelt <palmer@dabbelt.com>
+Cc: Paul Walmsley <paul.walmsley@sifive.com>
+Cc: Samuel Holland <samuel@sholland.org>
+Cc: Marc Zyngier <maz@kernel.org>
+Cc: Guo Ren <guoren@kernel.org>
+Cc: linux-riscv@lists.infradead.org
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20240131081933.144512-1-namcao@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-sifive-plic.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/irqchip/irq-sifive-plic.c
++++ b/drivers/irqchip/irq-sifive-plic.c
+@@ -144,7 +144,13 @@ static void plic_irq_eoi(struct irq_data
+ {
+ struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
+
+- writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
++ if (unlikely(irqd_irq_disabled(d))) {
++ plic_toggle(handler, d->hwirq, 1);
++ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
++ plic_toggle(handler, d->hwirq, 0);
++ } else {
++ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
++ }
+ }
+
+ #ifdef CONFIG_SMP
--- /dev/null
+From 8d3a7dfb801d157ac423261d7cd62c33e95375f8 Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Wed, 21 Feb 2024 09:27:31 +0000
+Subject: KVM: arm64: vgic-its: Test for valid IRQ in its_sync_lpi_pending_table()
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit 8d3a7dfb801d157ac423261d7cd62c33e95375f8 upstream.
+
+vgic_get_irq() may not return a valid descriptor if there is no ITS that
+holds a valid translation for the specified INTID. If that is the case,
+it is safe to silently ignore it and continue processing the LPI pending
+table.
+
+Cc: stable@vger.kernel.org
+Fixes: 33d3bc9556a7 ("KVM: arm64: vgic-its: Read initial LPI pending table")
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Link: https://lore.kernel.org/r/20240221092732.4126848-2-oliver.upton@linux.dev
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic-its.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm64/kvm/vgic/vgic-its.c
++++ b/arch/arm64/kvm/vgic/vgic-its.c
+@@ -462,6 +462,9 @@ static int its_sync_lpi_pending_table(st
+ }
+
+ irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
++ if (!irq)
++ continue;
++
+ raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ irq->pending_latch = pendmask & (1U << bit_nr);
+ vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
--- /dev/null
+From 85a71ee9a0700f6c18862ef3b0011ed9dad99aca Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Wed, 21 Feb 2024 09:27:32 +0000
+Subject: KVM: arm64: vgic-its: Test for valid IRQ in MOVALL handler
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit 85a71ee9a0700f6c18862ef3b0011ed9dad99aca upstream.
+
+It is possible that an LPI mapped in a different ITS gets unmapped while
+handling the MOVALL command. If that is the case, there is no state that
+can be migrated to the destination. Silently ignore it and continue
+migrating other LPIs.
+
+Cc: stable@vger.kernel.org
+Fixes: ff9c114394aa ("KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE")
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Link: https://lore.kernel.org/r/20240221092732.4126848-3-oliver.upton@linux.dev
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic-its.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm64/kvm/vgic/vgic-its.c
++++ b/arch/arm64/kvm/vgic/vgic-its.c
+@@ -1427,6 +1427,8 @@ static int vgic_its_cmd_handle_movall(st
+
+ for (i = 0; i < irq_count; i++) {
+ irq = vgic_get_irq(kvm, NULL, intids[i]);
++ if (!irq)
++ continue;
+
+ update_affinity(irq, vcpu2);
+
--- /dev/null
+From 359e54a93ab43d32ee1bff3c2f9f10cb9f6b6e79 Mon Sep 17 00:00:00 2001
+From: Tom Parkin <tparkin@katalix.com>
+Date: Tue, 20 Feb 2024 12:21:56 +0000
+Subject: l2tp: pass correct message length to ip6_append_data
+
+From: Tom Parkin <tparkin@katalix.com>
+
+commit 359e54a93ab43d32ee1bff3c2f9f10cb9f6b6e79 upstream.
+
+l2tp_ip6_sendmsg needs to avoid accounting for the transport header
+twice when splicing more data into an already partially-occupied skbuff.
+
+To manage this, we check whether the skbuff contains data using
+skb_queue_empty when deciding how much data to append using
+ip6_append_data.
+
+However, the code which performed the calculation was incorrect:
+
+ ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
+
+...due to C operator precedence, this ends up setting ulen to
+transhdrlen for messages with a non-zero length, which results in
+corrupted packets on the wire.
+
+Add parentheses to correct the calculation in line with the original
+intent.
+
+Fixes: 9d4c75800f61 ("ipv4, ipv6: Fix handling of transhdrlen in __ip{,6}_append_data()")
+Cc: David Howells <dhowells@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Tom Parkin <tparkin@katalix.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20240220122156.43131-1-tparkin@katalix.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_ip6.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -630,7 +630,7 @@ static int l2tp_ip6_sendmsg(struct sock
+
+ back_from_confirm:
+ lock_sock(sk);
+- ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0;
++ ulen = len + (skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0);
+ err = ip6_append_data(sk, ip_generic_getfrag, msg,
+ ulen, transhdrlen, &ipc6,
+ &fl6, (struct rt6_info *)dst,
--- /dev/null
+From 1001db6c42e4012b55e5ee19405490f23e033b5a Mon Sep 17 00:00:00 2001
+From: Huacai Chen <chenhuacai@loongson.cn>
+Date: Fri, 23 Feb 2024 14:36:31 +0800
+Subject: LoongArch: Disable IRQ before init_fn() for nonboot CPUs
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+commit 1001db6c42e4012b55e5ee19405490f23e033b5a upstream.
+
+Disable IRQ before init_fn() for nonboot CPUs when hotplug, in order to
+silence such warnings (and also avoid potential errors due to unexpected
+interrupts):
+
+WARNING: CPU: 1 PID: 0 at kernel/rcu/tree.c:4503 rcu_cpu_starting+0x214/0x280
+CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.6.17+ #1198
+pc 90000000048e3334 ra 90000000047bd56c tp 900000010039c000 sp 900000010039fdd0
+a0 0000000000000001 a1 0000000000000006 a2 900000000802c040 a3 0000000000000000
+a4 0000000000000001 a5 0000000000000004 a6 0000000000000000 a7 90000000048e3f4c
+t0 0000000000000001 t1 9000000005c70968 t2 0000000004000000 t3 000000000005e56e
+t4 00000000000002e4 t5 0000000000001000 t6 ffffffff80000000 t7 0000000000040000
+t8 9000000007931638 u0 0000000000000006 s9 0000000000000004 s0 0000000000000001
+s1 9000000006356ac0 s2 9000000007244000 s3 0000000000000001 s4 0000000000000001
+s5 900000000636f000 s6 7fffffffffffffff s7 9000000002123940 s8 9000000001ca55f8
+ ra: 90000000047bd56c tlb_init+0x24c/0x528
+ ERA: 90000000048e3334 rcu_cpu_starting+0x214/0x280
+ CRMD: 000000b0 (PLV0 -IE -DA +PG DACF=CC DACM=CC -WE)
+ PRMD: 00000000 (PPLV0 -PIE -PWE)
+ EUEN: 00000000 (-FPE -SXE -ASXE -BTE)
+ ECFG: 00071000 (LIE=12 VS=7)
+ESTAT: 000c0000 [BRK] (IS= ECode=12 EsubCode=0)
+ PRID: 0014c010 (Loongson-64bit, Loongson-3A5000)
+CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.6.17+ #1198
+Stack : 0000000000000000 9000000006375000 9000000005b61878 900000010039c000
+ 900000010039fa30 0000000000000000 900000010039fa38 900000000619a140
+ 9000000006456888 9000000006456880 900000010039f950 0000000000000001
+ 0000000000000001 cb0cb028ec7e52e1 0000000002b90000 9000000100348700
+ 0000000000000000 0000000000000001 ffffffff916d12f1 0000000000000003
+ 0000000000040000 9000000007930370 0000000002b90000 0000000000000004
+ 9000000006366000 900000000619a140 0000000000000000 0000000000000004
+ 0000000000000000 0000000000000009 ffffffffffc681f2 9000000002123940
+ 9000000001ca55f8 9000000006366000 90000000047a4828 00007ffff057ded8
+ 00000000000000b0 0000000000000000 0000000000000000 0000000000071000
+ ...
+Call Trace:
+[<90000000047a4828>] show_stack+0x48/0x1a0
+[<9000000005b61874>] dump_stack_lvl+0x84/0xcc
+[<90000000047f60ac>] __warn+0x8c/0x1e0
+[<9000000005b0ab34>] report_bug+0x1b4/0x280
+[<9000000005b63110>] do_bp+0x2d0/0x480
+[<90000000047a2e20>] handle_bp+0x120/0x1c0
+[<90000000048e3334>] rcu_cpu_starting+0x214/0x280
+[<90000000047bd568>] tlb_init+0x248/0x528
+[<90000000047a4c44>] per_cpu_trap_init+0x124/0x160
+[<90000000047a19f4>] cpu_probe+0x494/0xa00
+[<90000000047b551c>] start_secondary+0x3c/0xc0
+[<9000000005b66134>] smpboot_entry+0x50/0x58
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/loongarch/kernel/smp.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/loongarch/kernel/smp.c
++++ b/arch/loongarch/kernel/smp.c
+@@ -297,6 +297,7 @@ void play_dead(void)
+ addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0);
+ } while (addr == 0);
+
++ local_irq_disable();
+ init_fn = (void *)TO_CACHE(addr);
+ iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR);
+
--- /dev/null
+From 855678ed8534518e2b428bcbcec695de9ba248e8 Mon Sep 17 00:00:00 2001
+From: Yu Kuai <yukuai3@huawei.com>
+Date: Thu, 1 Feb 2024 17:25:51 +0800
+Subject: md: Fix missing release of 'active_io' for flush
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+commit 855678ed8534518e2b428bcbcec695de9ba248e8 upstream.
+
+submit_flushes
+ atomic_set(&mddev->flush_pending, 1);
+ rdev_for_each_rcu(rdev, mddev)
+ atomic_inc(&mddev->flush_pending);
+ bi->bi_end_io = md_end_flush
+ submit_bio(bi);
+ /* flush io is done first */
+ md_end_flush
+ if (atomic_dec_and_test(&mddev->flush_pending))
+ percpu_ref_put(&mddev->active_io)
+ -> active_io is not released
+
+ if (atomic_dec_and_test(&mddev->flush_pending))
+ -> missing release of active_io
+
+For consequence, mddev_suspend() will wait for 'active_io' to be zero
+forever.
+
+Fix this problem by releasing 'active_io' in submit_flushes() if
+'flush_pending' is decreased to zero.
+
+Fixes: fa2bbff7b0b4 ("md: synchronize flush io with array reconfiguration")
+Cc: stable@vger.kernel.org # v6.1+
+Reported-by: Blazej Kucman <blazej.kucman@linux.intel.com>
+Closes: https://lore.kernel.org/lkml/20240130172524.0000417b@linux.intel.com/
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/20240201092559.910982-7-yukuai1@huaweicloud.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/md.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -564,8 +564,12 @@ static void submit_flushes(struct work_s
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+- if (atomic_dec_and_test(&mddev->flush_pending))
++ if (atomic_dec_and_test(&mddev->flush_pending)) {
++ /* The pair is percpu_ref_get() from md_flush_request() */
++ percpu_ref_put(&mddev->active_io);
++
+ queue_work(md_wq, &mddev->flush_work);
++ }
+ }
+
+ static void md_submit_flush_data(struct work_struct *ws)
--- /dev/null
+From 13d0599ab3b2ff17f798353f24bcbef1659d3cfc Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Fri, 16 Feb 2024 11:40:25 -0800
+Subject: mm/damon/lru_sort: fix quota status loss due to online tunings
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 13d0599ab3b2ff17f798353f24bcbef1659d3cfc upstream.
+
+For online parameters change, DAMON_LRU_SORT creates new schemes based on
+latest values of the parameters and replaces the old schemes with the new
+one. When creating it, the internal status of the quotas of the old
+schemes is not preserved. As a result, charging of the quota starts from
+zero after the online tuning. The data that collected to estimate the
+throughput of the scheme's action is also reset, and therefore the
+estimation should start from the scratch again. Because the throughput
+estimation is being used to convert the time quota to the effective size
+quota, this could result in temporal time quota inaccuracy. It would be
+recovered over time, though. In short, the quota accuracy could be
+temporarily degraded after online parameters update.
+
+Fix the problem by checking the case and copying the internal fields for
+the status.
+
+Link: https://lkml.kernel.org/r/20240216194025.9207-3-sj@kernel.org
+Fixes: 40e983cca927 ("mm/damon: introduce DAMON-based LRU-lists Sorting")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> [6.0+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/lru_sort.c | 43 ++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 36 insertions(+), 7 deletions(-)
+
+--- a/mm/damon/lru_sort.c
++++ b/mm/damon/lru_sort.c
+@@ -185,9 +185,21 @@ static struct damos *damon_lru_sort_new_
+ return damon_lru_sort_new_scheme(&pattern, DAMOS_LRU_DEPRIO);
+ }
+
++static void damon_lru_sort_copy_quota_status(struct damos_quota *dst,
++ struct damos_quota *src)
++{
++ dst->total_charged_sz = src->total_charged_sz;
++ dst->total_charged_ns = src->total_charged_ns;
++ dst->charged_sz = src->charged_sz;
++ dst->charged_from = src->charged_from;
++ dst->charge_target_from = src->charge_target_from;
++ dst->charge_addr_from = src->charge_addr_from;
++}
++
+ static int damon_lru_sort_apply_parameters(void)
+ {
+- struct damos *scheme;
++ struct damos *scheme, *hot_scheme, *cold_scheme;
++ struct damos *old_hot_scheme = NULL, *old_cold_scheme = NULL;
+ unsigned int hot_thres, cold_thres;
+ int err = 0;
+
+@@ -195,18 +207,35 @@ static int damon_lru_sort_apply_paramete
+ if (err)
+ return err;
+
++ damon_for_each_scheme(scheme, ctx) {
++ if (!old_hot_scheme) {
++ old_hot_scheme = scheme;
++ continue;
++ }
++ old_cold_scheme = scheme;
++ }
++
+ hot_thres = damon_max_nr_accesses(&damon_lru_sort_mon_attrs) *
+ hot_thres_access_freq / 1000;
+- scheme = damon_lru_sort_new_hot_scheme(hot_thres);
+- if (!scheme)
++ hot_scheme = damon_lru_sort_new_hot_scheme(hot_thres);
++ if (!hot_scheme)
+ return -ENOMEM;
+- damon_set_schemes(ctx, &scheme, 1);
++ if (old_hot_scheme)
++ damon_lru_sort_copy_quota_status(&hot_scheme->quota,
++ &old_hot_scheme->quota);
+
+ cold_thres = cold_min_age / damon_lru_sort_mon_attrs.aggr_interval;
+- scheme = damon_lru_sort_new_cold_scheme(cold_thres);
+- if (!scheme)
++ cold_scheme = damon_lru_sort_new_cold_scheme(cold_thres);
++ if (!cold_scheme) {
++ damon_destroy_scheme(hot_scheme);
+ return -ENOMEM;
+- damon_add_scheme(ctx, scheme);
++ }
++ if (old_cold_scheme)
++ damon_lru_sort_copy_quota_status(&cold_scheme->quota,
++ &old_cold_scheme->quota);
++
++ damon_set_schemes(ctx, &hot_scheme, 1);
++ damon_add_scheme(ctx, cold_scheme);
+
+ return damon_set_region_biggest_system_ram_default(target,
+ &monitor_region_start,
--- /dev/null
+From 118642d7f606fc9b9c92ee611275420320290ffb Mon Sep 17 00:00:00 2001
+From: Johannes Weiner <hannes@cmpxchg.org>
+Date: Tue, 13 Feb 2024 03:16:34 -0500
+Subject: mm: memcontrol: clarify swapaccount=0 deprecation warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Johannes Weiner <hannes@cmpxchg.org>
+
+commit 118642d7f606fc9b9c92ee611275420320290ffb upstream.
+
+The swapaccount deprecation warning is throwing false positives. Since we
+deprecated the knob and defaulted to enabling, the only reports we've been
+getting are from folks that set swapaccount=1. While this is a nice
+affirmation that always-enabling was the right choice, we certainly don't
+want to warn when users request the supported mode.
+
+Only warn when disabling is requested, and clarify the warning.
+
+[colin.i.king@gmail.com: spelling: "commdandline" -> "commandline"]
+ Link: https://lkml.kernel.org/r/20240215090544.1649201-1-colin.i.king@gmail.com
+Link: https://lkml.kernel.org/r/20240213081634.3652326-1-hannes@cmpxchg.org
+Fixes: b25806dcd3d5 ("mm: memcontrol: deprecate swapaccounting=0 mode")
+Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
+Reported-by: "Jonas Schäfer" <jonas@wielicki.name>
+Reported-by: Narcis Garcia <debianlists@actiu.net>
+Suggested-by: Yosry Ahmed <yosryahmed@google.com>
+Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
+Reviewed-by: Yosry Ahmed <yosryahmed@google.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Acked-by: Shakeel Butt <shakeelb@google.com>
+Cc: Roman Gushchin <roman.gushchin@linux.dev>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memcontrol.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -7517,9 +7517,13 @@ bool mem_cgroup_swap_full(struct folio *
+
+ static int __init setup_swap_account(char *s)
+ {
+- pr_warn_once("The swapaccount= commandline option is deprecated. "
+- "Please report your usecase to linux-mm@kvack.org if you "
+- "depend on this functionality.\n");
++ bool res;
++
++ if (!kstrtobool(s, &res) && !res)
++ pr_warn_once("The swapaccount=0 commandline option is deprecated "
++ "in favor of configuring swap control via cgroupfs. "
++ "Please report your usecase to linux-mm@kvack.org if you "
++ "depend on this functionality.\n");
+ return 1;
+ }
+ __setup("swapaccount=", setup_swap_account);
--- /dev/null
+From 13ddaf26be324a7f951891ecd9ccd04466d27458 Mon Sep 17 00:00:00 2001
+From: Kairui Song <kasong@tencent.com>
+Date: Wed, 7 Feb 2024 02:25:59 +0800
+Subject: mm/swap: fix race when skipping swapcache
+
+From: Kairui Song <kasong@tencent.com>
+
+commit 13ddaf26be324a7f951891ecd9ccd04466d27458 upstream.
+
+When skipping swapcache for SWP_SYNCHRONOUS_IO, if two or more threads
+swapin the same entry at the same time, they get different pages (A, B).
+Before one thread (T0) finishes the swapin and installs page (A) to the
+PTE, another thread (T1) could finish swapin of page (B), swap_free the
+entry, then swap out the possibly modified page reusing the same entry.
+It breaks the pte_same check in (T0) because PTE value is unchanged,
+causing ABA problem. Thread (T0) will install a stalled page (A) into the
+PTE and cause data corruption.
+
+One possible callstack is like this:
+
+CPU0 CPU1
+---- ----
+do_swap_page() do_swap_page() with same entry
+<direct swapin path> <direct swapin path>
+<alloc page A> <alloc page B>
+swap_read_folio() <- read to page A swap_read_folio() <- read to page B
+<slow on later locks or interrupt> <finished swapin first>
+... set_pte_at()
+ swap_free() <- entry is free
+ <write to page B, now page A stalled>
+ <swap out page B to same swap entry>
+pte_same() <- Check pass, PTE seems
+ unchanged, but page A
+ is stalled!
+swap_free() <- page B content lost!
+set_pte_at() <- staled page A installed!
+
+And besides, for ZRAM, swap_free() allows the swap device to discard the
+entry content, so even if page (B) is not modified, if swap_read_folio()
+on CPU0 happens later than swap_free() on CPU1, it may also cause data
+loss.
+
+To fix this, reuse swapcache_prepare which will pin the swap entry using
+the cache flag, and allow only one thread to swap it in, also prevent any
+parallel code from putting the entry in the cache. Release the pin after
+PT unlocked.
+
+Racers just loop and wait since it's a rare and very short event. A
+schedule_timeout_uninterruptible(1) call is added to avoid repeated page
+faults wasting too much CPU, causing livelock or adding too much noise to
+perf statistics. A similar livelock issue was described in commit
+029c4628b2eb ("mm: swap: get rid of livelock in swapin readahead")
+
+Reproducer:
+
+This race issue can be triggered easily using a well constructed
+reproducer and patched brd (with a delay in read path) [1]:
+
+With latest 6.8 mainline, race caused data loss can be observed easily:
+$ gcc -g -lpthread test-thread-swap-race.c && ./a.out
+ Polulating 32MB of memory region...
+ Keep swapping out...
+ Starting round 0...
+ Spawning 65536 workers...
+ 32746 workers spawned, wait for done...
+ Round 0: Error on 0x5aa00, expected 32746, got 32743, 3 data loss!
+ Round 0: Error on 0x395200, expected 32746, got 32743, 3 data loss!
+ Round 0: Error on 0x3fd000, expected 32746, got 32737, 9 data loss!
+ Round 0 Failed, 15 data loss!
+
+This reproducer spawns multiple threads sharing the same memory region
+using a small swap device. Every two threads updates mapped pages one by
+one in opposite direction trying to create a race, with one dedicated
+thread keep swapping out the data out using madvise.
+
+The reproducer created a reproduce rate of about once every 5 minutes, so
+the race should be totally possible in production.
+
+After this patch, I ran the reproducer for over a few hundred rounds and
+no data loss observed.
+
+Performance overhead is minimal, microbenchmark swapin 10G from 32G
+zram:
+
+Before: 10934698 us
+After: 11157121 us
+Cached: 13155355 us (Dropping SWP_SYNCHRONOUS_IO flag)
+
+[kasong@tencent.com: v4]
+ Link: https://lkml.kernel.org/r/20240219082040.7495-1-ryncsn@gmail.com
+Link: https://lkml.kernel.org/r/20240206182559.32264-1-ryncsn@gmail.com
+Fixes: 0bcac06f27d7 ("mm, swap: skip swapcache for swapin of synchronous device")
+Reported-by: "Huang, Ying" <ying.huang@intel.com>
+Closes: https://lore.kernel.org/lkml/87bk92gqpx.fsf_-_@yhuang6-desk2.ccr.corp.intel.com/
+Link: https://github.com/ryncsn/emm-test-project/tree/master/swap-stress-race [1]
+Signed-off-by: Kairui Song <kasong@tencent.com>
+Reviewed-by: "Huang, Ying" <ying.huang@intel.com>
+Acked-by: Yu Zhao <yuzhao@google.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Acked-by: Chris Li <chrisl@kernel.org>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Yosry Ahmed <yosryahmed@google.com>
+Cc: Yu Zhao <yuzhao@google.com>
+Cc: Barry Song <21cnbao@gmail.com>
+Cc: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/swap.h | 5 +++++
+ mm/memory.c | 20 ++++++++++++++++++++
+ mm/swap.h | 5 +++++
+ mm/swapfile.c | 13 +++++++++++++
+ 4 files changed, 43 insertions(+)
+
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -571,6 +571,11 @@ static inline int swap_duplicate(swp_ent
+ return 0;
+ }
+
++static inline int swapcache_prepare(swp_entry_t swp)
++{
++ return 0;
++}
++
+ static inline void swap_free(swp_entry_t swp)
+ {
+ }
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -3761,6 +3761,7 @@ vm_fault_t do_swap_page(struct vm_fault
+ struct page *page;
+ struct swap_info_struct *si = NULL;
+ rmap_t rmap_flags = RMAP_NONE;
++ bool need_clear_cache = false;
+ bool exclusive = false;
+ swp_entry_t entry;
+ pte_t pte;
+@@ -3822,6 +3823,20 @@ vm_fault_t do_swap_page(struct vm_fault
+ if (!folio) {
+ if (data_race(si->flags & SWP_SYNCHRONOUS_IO) &&
+ __swap_count(entry) == 1) {
++ /*
++ * Prevent parallel swapin from proceeding with
++ * the cache flag. Otherwise, another thread may
++ * finish swapin first, free the entry, and swapout
++ * reusing the same entry. It's undetectable as
++ * pte_same() returns true due to entry reuse.
++ */
++ if (swapcache_prepare(entry)) {
++ /* Relax a bit to prevent rapid repeated page faults */
++ schedule_timeout_uninterruptible(1);
++ goto out;
++ }
++ need_clear_cache = true;
++
+ /* skip swapcache */
+ folio = vma_alloc_folio(GFP_HIGHUSER_MOVABLE, 0,
+ vma, vmf->address, false);
+@@ -4073,6 +4088,9 @@ vm_fault_t do_swap_page(struct vm_fault
+ unlock:
+ pte_unmap_unlock(vmf->pte, vmf->ptl);
+ out:
++ /* Clear the swap cache pin for direct swapin after PTL unlock */
++ if (need_clear_cache)
++ swapcache_clear(si, entry);
+ if (si)
+ put_swap_device(si);
+ return ret;
+@@ -4086,6 +4104,8 @@ out_release:
+ folio_unlock(swapcache);
+ folio_put(swapcache);
+ }
++ if (need_clear_cache)
++ swapcache_clear(si, entry);
+ if (si)
+ put_swap_device(si);
+ return ret;
+--- a/mm/swap.h
++++ b/mm/swap.h
+@@ -39,6 +39,7 @@ void __delete_from_swap_cache(struct fol
+ void delete_from_swap_cache(struct folio *folio);
+ void clear_shadow_from_swap_cache(int type, unsigned long begin,
+ unsigned long end);
++void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry);
+ struct folio *swap_cache_get_folio(swp_entry_t entry,
+ struct vm_area_struct *vma, unsigned long addr);
+ struct page *find_get_incore_page(struct address_space *mapping, pgoff_t index);
+@@ -98,6 +99,10 @@ static inline int swap_writepage(struct
+ return 0;
+ }
+
++static inline void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry)
++{
++}
++
+ static inline struct folio *swap_cache_get_folio(swp_entry_t entry,
+ struct vm_area_struct *vma, unsigned long addr)
+ {
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -3373,6 +3373,19 @@ int swapcache_prepare(swp_entry_t entry)
+ return __swap_duplicate(entry, SWAP_HAS_CACHE);
+ }
+
++void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry)
++{
++ struct swap_cluster_info *ci;
++ unsigned long offset = swp_offset(entry);
++ unsigned char usage;
++
++ ci = lock_cluster_or_swap_info(si, offset);
++ usage = __swap_entry_free_locked(si, offset, SWAP_HAS_CACHE);
++ unlock_cluster_or_swap_info(si, ci);
++ if (!usage)
++ free_swap_slot(entry);
++}
++
+ struct swap_info_struct *swp_swap_info(swp_entry_t entry)
+ {
+ return swap_type_to_swap_info(swp_type(entry));
--- /dev/null
+From db744ddd59be798c2627efbfc71f707f5a935a40 Mon Sep 17 00:00:00 2001
+From: Vidya Sagar <vidyas@nvidia.com>
+Date: Mon, 15 Jan 2024 19:26:49 +0530
+Subject: PCI/MSI: Prevent MSI hardware interrupt number truncation
+
+From: Vidya Sagar <vidyas@nvidia.com>
+
+commit db744ddd59be798c2627efbfc71f707f5a935a40 upstream.
+
+While calculating the hardware interrupt number for a MSI interrupt, the
+higher bits (i.e. from bit-5 onwards a.k.a domain_nr >= 32) of the PCI
+domain number gets truncated because of the shifted value casting to return
+type of pci_domain_nr() which is 'int'. This for example is resulting in
+same hardware interrupt number for devices 0019:00:00.0 and 0039:00:00.0.
+
+To address this cast the PCI domain number to 'irq_hw_number_t' before left
+shifting it to calculate the hardware interrupt number.
+
+Please note that this fixes the issue only on 64-bit systems and doesn't
+change the behavior for 32-bit systems i.e. the 32-bit systems continue to
+have the issue. Since the issue surfaces only if there are too many PCIe
+controllers in the system which usually is the case in modern server
+systems and they don't tend to run 32-bit kernels.
+
+Fixes: 3878eaefb89a ("PCI/MSI: Enhance core to support hierarchy irqdomain")
+Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Shanker Donthineni <sdonthineni@nvidia.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240115135649.708536-1-vidyas@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi/irqdomain.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/msi/irqdomain.c
++++ b/drivers/pci/msi/irqdomain.c
+@@ -60,7 +60,7 @@ static irq_hw_number_t pci_msi_domain_ca
+
+ return (irq_hw_number_t)desc->msi_index |
+ pci_dev_id(dev) << 11 |
+- (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
++ ((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27;
+ }
+
+ static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
--- /dev/null
+From 84c16d01ff219bc0a5dca5219db6b8b86a6854fb Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 16 Feb 2024 21:33:00 +0100
+Subject: platform/x86: intel-vbtn: Stop calling "VBDL" from notify_handler
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 84c16d01ff219bc0a5dca5219db6b8b86a6854fb upstream.
+
+Commit 14c200b7ca46 ("platform/x86: intel-vbtn: Fix missing
+tablet-mode-switch events") causes 2 issues on the ThinkPad X1 Tablet Gen2:
+
+1. The ThinkPad will wake up immediately from suspend
+2. When put in tablet mode SW_TABLET_MODE reverts to 0 after about 1 second
+
+Both these issues are caused by the "VBDL" ACPI method call added
+at the end of the notify_handler.
+
+And it never became entirely clear if this call is even necessary to fix
+the issue of missing tablet-mode-switch events on the Dell Inspiron 7352.
+
+Drop the "VBDL" ACPI method call again to fix the 2 issues this is
+causing on the ThinkPad X1 Tablet Gen2.
+
+Fixes: 14c200b7ca46 ("platform/x86: intel-vbtn: Fix missing tablet-mode-switch events")
+Reported-by: Alexander Kobel <a-kobel@a-kobel.de>
+Closes: https://lore.kernel.org/platform-driver-x86/295984ce-bd4b-49bd-adc5-ffe7c898d7f0@a-kobel.de/
+Cc: regressions@lists.linux.dev
+Cc: Arnold Gozum <arngozum@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Tested-by: Alexander Kobel <a-kobel@a-kobel.de>
+Link: https://lore.kernel.org/r/20240216203300.245826-1-hdegoede@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/intel/vbtn.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/platform/x86/intel/vbtn.c
++++ b/drivers/platform/x86/intel/vbtn.c
+@@ -200,9 +200,6 @@ static void notify_handler(acpi_handle h
+ autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
+
+ sparse_keymap_report_event(input_dev, event, val, autorelease);
+-
+- /* Some devices need this to report further events */
+- acpi_evaluate_object(handle, "VBDL", NULL, NULL);
+ }
+
+ /*
--- /dev/null
+From dbcbfd662a725641d118fb3ae5ffb7be4e3d0fb0 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 12 Feb 2024 13:06:07 +0100
+Subject: platform/x86: touchscreen_dmi: Allow partial (prefix) matches for ACPI names
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit dbcbfd662a725641d118fb3ae5ffb7be4e3d0fb0 upstream.
+
+On some devices the ACPI name of the touchscreen is e.g. either
+MSSL1680:00 or MSSL1680:01 depending on the BIOS version.
+
+This happens for example on the "Chuwi Hi8 Air" tablet where the initial
+commit's ts_data uses "MSSL1680:00" but the tablets from the github issue
+and linux-hardware.org probe linked below both use "MSSL1680:01".
+
+Replace the strcmp() match on ts_data->acpi_name with a strstarts()
+check to allow using a partial match on just the ACPI HID of "MSSL1680"
+and change the ts_data->acpi_name for the "Chuwi Hi8 Air" accordingly
+to fix the touchscreen not working on models where it is "MSSL1680:01".
+
+Note this drops the length check for I2C_NAME_SIZE. This never was
+necessary since the ACPI names used are never more then 11 chars and
+I2C_NAME_SIZE is 20 so the replaced strncmp() would always stop long
+before reaching I2C_NAME_SIZE.
+
+Link: https://linux-hardware.org/?computer=AC4301C0542A
+Fixes: bbb97d728f77 ("platform/x86: touchscreen_dmi: Add info for the Chuwi Hi8 Air tablet")
+Closes: https://github.com/onitake/gsl-firmware/issues/91
+Cc: stable@vger.kernel.org
+Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240212120608.30469-1-hdegoede@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/touchscreen_dmi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/platform/x86/touchscreen_dmi.c
++++ b/drivers/platform/x86/touchscreen_dmi.c
+@@ -50,7 +50,7 @@ static const struct property_entry chuwi
+ };
+
+ static const struct ts_dmi_data chuwi_hi8_air_data = {
+- .acpi_name = "MSSL1680:00",
++ .acpi_name = "MSSL1680",
+ .properties = chuwi_hi8_air_props,
+ };
+
+@@ -1776,7 +1776,7 @@ static void ts_dmi_add_props(struct i2c_
+ int error;
+
+ if (has_acpi_companion(dev) &&
+- !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
++ strstarts(client->name, ts_data->acpi_name)) {
+ error = device_create_managed_software_node(dev, ts_data->properties, NULL);
+ if (error)
+ dev_err(dev, "failed to add properties: %d\n", error);
--- /dev/null
+From 82b143aeb169b8b55798d7d2063032e1a6ceeeb0 Mon Sep 17 00:00:00 2001
+From: Helge Deller <deller@gmx.de>
+Date: Mon, 5 Feb 2024 10:39:20 +0100
+Subject: Revert "parisc: Only list existing CPUs in cpu_possible_mask"
+
+From: Helge Deller <deller@gmx.de>
+
+commit 82b143aeb169b8b55798d7d2063032e1a6ceeeb0 upstream.
+
+This reverts commit 0921244f6f4f0d05698b953fe632a99b38907226.
+
+It broke CPU hotplugging because it modifies the __cpu_possible_mask
+after bootup, so that it will be different than nr_cpu_ids, which
+then effictively breaks the workqueue setup code and triggers crashes
+when shutting down CPUs at runtime.
+
+Guenter was the first who noticed the wrong values in __cpu_possible_mask,
+since the cpumask Kunit tests were failig.
+
+Reverting this commit fixes both issues, but sadly brings back this
+uncritical runtime warning:
+register_cpu_capacity_sysctl: too early to get CPU4 device!
+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lkml.org/lkml/2024/2/4/146
+Link: https://lore.kernel.org/lkml/Zb0mbHlIud_bqftx@slm.duckdns.org/t/
+Cc: stable@vger.kernel.org # 6.0+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/parisc/kernel/processor.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/arch/parisc/kernel/processor.c
++++ b/arch/parisc/kernel/processor.c
+@@ -171,7 +171,6 @@ static int __init processor_probe(struct
+ p->cpu_num = cpu_info.cpu_num;
+ p->cpu_loc = cpu_info.cpu_loc;
+
+- set_cpu_possible(cpuid, true);
+ store_cpu_topology(cpuid);
+
+ #ifdef CONFIG_SMP
+@@ -466,13 +465,6 @@ static struct parisc_driver cpu_driver _
+ */
+ void __init processor_init(void)
+ {
+- unsigned int cpu;
+-
+ reset_cpu_topology();
+-
+- /* reset possible mask. We will mark those which are possible. */
+- for_each_possible_cpu(cpu)
+- set_cpu_possible(cpu, false);
+-
+ register_parisc_driver(&cpu_driver);
+ }
--- /dev/null
+From 5ef1dc40ffa6a6cb968b0fdc43c3a61727a9e950 Mon Sep 17 00:00:00 2001
+From: Peter Oberparleiter <oberpar@linux.ibm.com>
+Date: Wed, 14 Feb 2024 16:06:28 +0100
+Subject: s390/cio: fix invalid -EBUSY on ccw_device_start
+
+From: Peter Oberparleiter <oberpar@linux.ibm.com>
+
+commit 5ef1dc40ffa6a6cb968b0fdc43c3a61727a9e950 upstream.
+
+The s390 common I/O layer (CIO) returns an unexpected -EBUSY return code
+when drivers try to start I/O while a path-verification (PV) process is
+pending. This can lead to failed device initialization attempts with
+symptoms like broken network connectivity after boot.
+
+Fix this by replacing the -EBUSY return code with a deferred condition
+code 1 reply to make path-verification handling consistent from a
+driver's point of view.
+
+The problem can be reproduced semi-regularly using the following process,
+while repeating steps 2-3 as necessary (example assumes an OSA device
+with bus-IDs 0.0.a000-0.0.a002 on CHPID 0.02):
+
+1. echo 0.0.a000,0.0.a001,0.0.a002 >/sys/bus/ccwgroup/drivers/qeth/group
+2. echo 0 > /sys/bus/ccwgroup/devices/0.0.a000/online
+3. echo 1 > /sys/bus/ccwgroup/devices/0.0.a000/online ; \
+ echo on > /sys/devices/css0/chp0.02/status
+
+Background information:
+
+The common I/O layer starts path-verification I/Os when it receives
+indications about changes in a device path's availability. This occurs
+for example when hardware events indicate a change in channel-path
+status, or when a manual operation such as a CHPID vary or configure
+operation is performed.
+
+If a driver attempts to start I/O while a PV is running, CIO reports a
+successful I/O start (ccw_device_start() return code 0). Then, after
+completion of PV, CIO synthesizes an interrupt response that indicates
+an asynchronous status condition that prevented the start of the I/O
+(deferred condition code 1).
+
+If a PV indication arrives while a device is busy with driver-owned I/O,
+PV is delayed until after I/O completion was reported to the driver's
+interrupt handler. To ensure that PV can be started eventually, CIO
+reports a device busy condition (ccw_device_start() return code -EBUSY)
+if a driver tries to start another I/O while PV is pending.
+
+In some cases this -EBUSY return code causes device drivers to consider
+a device not operational, resulting in failed device initialization.
+
+Note: The code that introduced the problem was added in 2003. Symptoms
+started appearing with the following CIO commit that causes a PV
+indication when a device is removed from the cio_ignore list after the
+associated parent subchannel device was probed, but before online
+processing of the CCW device has started:
+
+2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers")
+
+During boot, the cio_ignore list is modified by the cio_ignore dracut
+module [1] as well as Linux vendor-specific systemd service scripts[2].
+When combined, this commit and boot scripts cause a frequent occurrence
+of the problem during boot.
+
+[1] https://github.com/dracutdevs/dracut/tree/master/modules.d/81cio_ignore
+[2] https://github.com/SUSE/s390-tools/blob/master/cio_ignore.service
+
+Cc: stable@vger.kernel.org # v5.15+
+Fixes: 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers")
+Tested-By: Thorsten Winkler <twinkler@linux.ibm.com>
+Reviewed-by: Thorsten Winkler <twinkler@linux.ibm.com>
+Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/s390/cio/device_ops.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/s390/cio/device_ops.c
++++ b/drivers/s390/cio/device_ops.c
+@@ -202,7 +202,8 @@ int ccw_device_start_timeout_key(struct
+ return -EINVAL;
+ if (cdev->private->state == DEV_STATE_NOT_OPER)
+ return -ENODEV;
+- if (cdev->private->state == DEV_STATE_VERIFY) {
++ if (cdev->private->state == DEV_STATE_VERIFY ||
++ cdev->private->flags.doverify) {
+ /* Remember to fake irb when finished. */
+ if (!cdev->private->flags.fake_irb) {
+ cdev->private->flags.fake_irb = FAKE_CMD_IRB;
+@@ -214,8 +215,7 @@ int ccw_device_start_timeout_key(struct
+ }
+ if (cdev->private->state != DEV_STATE_ONLINE ||
+ ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
+- !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) ||
+- cdev->private->flags.doverify)
++ !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)))
+ return -EBUSY;
+ ret = cio_set_options (sch, flags);
+ if (ret)
--- /dev/null
+From b5fc07a5fb56216a49e6c1d0b172d5464d99a89b Mon Sep 17 00:00:00 2001
+From: "Martin K. Petersen" <martin.petersen@oracle.com>
+Date: Wed, 14 Feb 2024 17:14:11 -0500
+Subject: scsi: core: Consult supported VPD page list prior to fetching page
+
+From: Martin K. Petersen <martin.petersen@oracle.com>
+
+commit b5fc07a5fb56216a49e6c1d0b172d5464d99a89b upstream.
+
+Commit c92a6b5d6335 ("scsi: core: Query VPD size before getting full
+page") removed the logic which checks whether a VPD page is present on
+the supported pages list before asking for the page itself. That was
+done because SPC helpfully states "The Supported VPD Pages VPD page
+list may or may not include all the VPD pages that are able to be
+returned by the device server". Testing had revealed a few devices
+that supported some of the 0xBn pages but didn't actually list them in
+page 0.
+
+Julian Sikorski bisected a problem with his drive resetting during
+discovery to the commit above. As it turns out, this particular drive
+firmware will crash if we attempt to fetch page 0xB9.
+
+Various approaches were attempted to work around this. In the end,
+reinstating the logic that consults VPD page 0 before fetching any
+other page was the path of least resistance. A firmware update for the
+devices which originally compelled us to remove the check has since
+been released.
+
+Link: https://lore.kernel.org/r/20240214221411.2888112-1-martin.petersen@oracle.com
+Fixes: c92a6b5d6335 ("scsi: core: Query VPD size before getting full page")
+Cc: stable@vger.kernel.org
+Cc: Bart Van Assche <bvanassche@acm.org>
+Reported-by: Julian Sikorski <belegdol@gmail.com>
+Tested-by: Julian Sikorski <belegdol@gmail.com>
+Reviewed-by: Lee Duncan <lee.duncan@suse.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/scsi.c | 22 ++++++++++++++++++++--
+ include/scsi/scsi_device.h | 4 ----
+ 2 files changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/scsi/scsi.c
++++ b/drivers/scsi/scsi.c
+@@ -328,21 +328,39 @@ static int scsi_vpd_inquiry(struct scsi_
+ return result + 4;
+ }
+
++enum scsi_vpd_parameters {
++ SCSI_VPD_HEADER_SIZE = 4,
++ SCSI_VPD_LIST_SIZE = 36,
++};
++
+ static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page)
+ {
+- unsigned char vpd_header[SCSI_VPD_HEADER_SIZE] __aligned(4);
++ unsigned char vpd[SCSI_VPD_LIST_SIZE] __aligned(4);
+ int result;
+
+ if (sdev->no_vpd_size)
+ return SCSI_DEFAULT_VPD_LEN;
+
+ /*
++ * Fetch the supported pages VPD and validate that the requested page
++ * number is present.
++ */
++ if (page != 0) {
++ result = scsi_vpd_inquiry(sdev, vpd, 0, sizeof(vpd));
++ if (result < SCSI_VPD_HEADER_SIZE)
++ return 0;
++
++ result -= SCSI_VPD_HEADER_SIZE;
++ if (!memchr(&vpd[SCSI_VPD_HEADER_SIZE], page, result))
++ return 0;
++ }
++ /*
+ * Fetch the VPD page header to find out how big the page
+ * is. This is done to prevent problems on legacy devices
+ * which can not handle allocation lengths as large as
+ * potentially requested by the caller.
+ */
+- result = scsi_vpd_inquiry(sdev, vpd_header, page, sizeof(vpd_header));
++ result = scsi_vpd_inquiry(sdev, vpd, page, SCSI_VPD_HEADER_SIZE);
+ if (result < 0)
+ return 0;
+
+--- a/include/scsi/scsi_device.h
++++ b/include/scsi/scsi_device.h
+@@ -100,10 +100,6 @@ struct scsi_vpd {
+ unsigned char data[];
+ };
+
+-enum scsi_vpd_parameters {
+- SCSI_VPD_HEADER_SIZE = 4,
+-};
+-
+ struct scsi_device {
+ struct Scsi_Host *host;
+ struct request_queue *request_queue;
--- /dev/null
+From de959094eb2197636f7c803af0943cb9d3b35804 Mon Sep 17 00:00:00 2001
+From: Naohiro Aota <naohiro.aota@wdc.com>
+Date: Wed, 14 Feb 2024 23:43:56 +0900
+Subject: scsi: target: pscsi: Fix bio_put() for error case
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+commit de959094eb2197636f7c803af0943cb9d3b35804 upstream.
+
+As of commit 066ff571011d ("block: turn bio_kmalloc into a simple kmalloc
+wrapper"), a bio allocated by bio_kmalloc() must be freed by bio_uninit()
+and kfree(). That is not done properly for the error case, hitting WARN and
+NULL pointer dereference in bio_free().
+
+Fixes: 066ff571011d ("block: turn bio_kmalloc into a simple kmalloc wrapper")
+CC: stable@vger.kernel.org # 6.1+
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Link: https://lore.kernel.org/r/20240214144356.101814-1-naohiro.aota@wdc.com
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/target/target_core_pscsi.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/target/target_core_pscsi.c
++++ b/drivers/target/target_core_pscsi.c
+@@ -910,12 +910,15 @@ new_bio:
+
+ return 0;
+ fail:
+- if (bio)
+- bio_put(bio);
++ if (bio) {
++ bio_uninit(bio);
++ kfree(bio);
++ }
+ while (req->bio) {
+ bio = req->bio;
+ req->bio = bio->bi_next;
+- bio_put(bio);
++ bio_uninit(bio);
++ kfree(bio);
+ }
+ req->biotail = NULL;
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
pmdomain-mediatek-fix-race-conditions-with-genpd.patch
pmdomain-renesas-r8a77980-sysc-cr7-must-be-always-on.patch
ib-hfi1-fix-sdma.h-tx-num_descs-off-by-one-error.patch
+loongarch-disable-irq-before-init_fn-for-nonboot-cpus.patch
+drm-ttm-fix-an-invalid-freeing-on-already-freed-page-in-error-path.patch
+s390-cio-fix-invalid-ebusy-on-ccw_device_start.patch
+ata-libata-core-do-not-try-to-set-sleeping-devices-to-standby.patch
+dm-crypt-recheck-the-integrity-tag-after-a-failure.patch
+revert-parisc-only-list-existing-cpus-in-cpu_possible_mask.patch
+dm-integrity-recheck-the-integrity-tag-after-a-failure.patch
+dm-crypt-don-t-modify-the-data-when-using-authenticated-encryption.patch
+dm-verity-recheck-the-hash-after-a-failure.patch
+cxl-pci-fix-disabling-memory-if-dvsec-cxl-range-does-not-match-a-cfmws-window.patch
+scsi-target-pscsi-fix-bio_put-for-error-case.patch
+scsi-core-consult-supported-vpd-page-list-prior-to-fetching-page.patch
+mm-swap-fix-race-when-skipping-swapcache.patch
+mm-damon-lru_sort-fix-quota-status-loss-due-to-online-tunings.patch
+mm-memcontrol-clarify-swapaccount-0-deprecation-warning.patch
+platform-x86-intel-vbtn-stop-calling-vbdl-from-notify_handler.patch
+platform-x86-touchscreen_dmi-allow-partial-prefix-matches-for-acpi-names.patch
+cachefiles-fix-memory-leak-in-cachefiles_add_cache.patch
+md-fix-missing-release-of-active_io-for-flush.patch
+kvm-arm64-vgic-its-test-for-valid-irq-in-movall-handler.patch
+kvm-arm64-vgic-its-test-for-valid-irq-in-its_sync_lpi_pending_table.patch
+gtp-fix-use-after-free-and-null-ptr-deref-in-gtp_genl_dump_pdp.patch
+crypto-virtio-akcipher-fix-stack-overflow-on-memcpy.patch
+irqchip-gic-v3-its-do-not-assume-vpe-tables-are-preallocated.patch
+irqchip-sifive-plic-enable-interrupt-if-needed-before-eoi.patch
+pci-msi-prevent-msi-hardware-interrupt-number-truncation.patch
+l2tp-pass-correct-message-length-to-ip6_append_data.patch