--- /dev/null
+From c0a40097f0bc81deafc15f9195d1fb54595cd6d0 Mon Sep 17 00:00:00 2001
+From: Dirk Behme <dirk.behme@de.bosch.com>
+Date: Mon, 13 May 2024 07:06:34 +0200
+Subject: drivers: core: synchronize really_probe() and dev_uevent()
+
+From: Dirk Behme <dirk.behme@de.bosch.com>
+
+commit c0a40097f0bc81deafc15f9195d1fb54595cd6d0 upstream.
+
+Synchronize the dev->driver usage in really_probe() and dev_uevent().
+These can run in different threads, what can result in the following
+race condition for dev->driver uninitialization:
+
+Thread #1:
+==========
+
+really_probe() {
+...
+probe_failed:
+...
+device_unbind_cleanup(dev) {
+ ...
+ dev->driver = NULL; // <= Failed probe sets dev->driver to NULL
+ ...
+ }
+...
+}
+
+Thread #2:
+==========
+
+dev_uevent() {
+...
+if (dev->driver)
+ // If dev->driver is NULLed from really_probe() from here on,
+ // after above check, the system crashes
+ add_uevent_var(env, "DRIVER=%s", dev->driver->name);
+...
+}
+
+really_probe() holds the lock, already. So nothing needs to be done
+there. dev_uevent() is called with lock held, often, too. But not
+always. What implies that we can't add any locking in dev_uevent()
+itself. So fix this race by adding the lock to the non-protected
+path. This is the path where above race is observed:
+
+ dev_uevent+0x235/0x380
+ uevent_show+0x10c/0x1f0 <= Add lock here
+ dev_attr_show+0x3a/0xa0
+ sysfs_kf_seq_show+0x17c/0x250
+ kernfs_seq_show+0x7c/0x90
+ seq_read_iter+0x2d7/0x940
+ kernfs_fop_read_iter+0xc6/0x310
+ vfs_read+0x5bc/0x6b0
+ ksys_read+0xeb/0x1b0
+ __x64_sys_read+0x42/0x50
+ x64_sys_call+0x27ad/0x2d30
+ do_syscall_64+0xcd/0x1d0
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Similar cases are reported by syzkaller in
+
+https://syzkaller.appspot.com/bug?extid=ffa8143439596313a85a
+
+But these are regarding the *initialization* of dev->driver
+
+dev->driver = drv;
+
+As this switches dev->driver to non-NULL these reports can be considered
+to be false-positives (which should be "fixed" by this commit, as well,
+though).
+
+The same issue was reported and tried to be fixed back in 2015 in
+
+https://lore.kernel.org/lkml/1421259054-2574-1-git-send-email-a.sangwan@samsung.com/
+
+already.
+
+Fixes: 239378f16aa1 ("Driver core: add uevent vars for devices of a class")
+Cc: stable <stable@kernel.org>
+Cc: syzbot+ffa8143439596313a85a@syzkaller.appspotmail.com
+Cc: Ashish Sangwan <a.sangwan@samsung.com>
+Cc: Namjae Jeon <namjae.jeon@samsung.com>
+Signed-off-by: Dirk Behme <dirk.behme@de.bosch.com>
+Link: https://lore.kernel.org/r/20240513050634.3964461-1-dirk.behme@de.bosch.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/core.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -2738,8 +2738,11 @@ static ssize_t uevent_show(struct device
+ if (!env)
+ return -ENOMEM;
+
++ /* Synchronize with really_probe() */
++ device_lock(dev);
+ /* let the kset specific function add its keys */
+ retval = kset->uevent_ops->uevent(&dev->kobj, env);
++ device_unlock(dev);
+ if (retval)
+ goto out;
+
--- /dev/null
+From 8a01ef749b0a632f0e1f4ead0f08b3310d99fcb1 Mon Sep 17 00:00:00 2001
+From: David Lechner <dlechner@baylibre.com>
+Date: Fri, 3 May 2024 14:45:05 -0500
+Subject: iio: adc: ad9467: fix scan type sign
+
+From: David Lechner <dlechner@baylibre.com>
+
+commit 8a01ef749b0a632f0e1f4ead0f08b3310d99fcb1 upstream.
+
+According to the IIO documentation, the sign in the scan type should be
+lower case. The ad9467 driver was incorrectly using upper case.
+
+Fix by changing to lower case.
+
+Fixes: 4606d0f4b05f ("iio: adc: ad9467: add support for AD9434 high-speed ADC")
+Fixes: ad6797120238 ("iio: adc: ad9467: add support AD9467 ADC")
+Signed-off-by: David Lechner <dlechner@baylibre.com>
+Link: https://lore.kernel.org/r/20240503-ad9467-fix-scan-type-sign-v1-1-c7a1a066ebb9@baylibre.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/adc/ad9467.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/iio/adc/ad9467.c
++++ b/drivers/iio/adc/ad9467.c
+@@ -225,11 +225,11 @@ static void __ad9467_get_scale(struct ad
+ }
+
+ static const struct iio_chan_spec ad9434_channels[] = {
+- AD9467_CHAN(0, 0, 12, 'S'),
++ AD9467_CHAN(0, 0, 12, 's'),
+ };
+
+ static const struct iio_chan_spec ad9467_channels[] = {
+- AD9467_CHAN(0, 0, 16, 'S'),
++ AD9467_CHAN(0, 0, 16, 's'),
+ };
+
+ static const struct ad9467_chip_info ad9467_chip_tbl = {
--- /dev/null
+From 279428df888319bf68f2686934897301a250bb84 Mon Sep 17 00:00:00 2001
+From: Marc Ferland <marc.ferland@sonatest.com>
+Date: Wed, 1 May 2024 11:05:54 -0400
+Subject: iio: dac: ad5592r: fix temperature channel scaling value
+
+From: Marc Ferland <marc.ferland@sonatest.com>
+
+commit 279428df888319bf68f2686934897301a250bb84 upstream.
+
+The scale value for the temperature channel is (assuming Vref=2.5 and
+the datasheet):
+
+ 376.7897513
+
+When calculating both val and val2 for the temperature scale we
+use (3767897513/25) and multiply it by Vref (here I assume 2500mV) to
+obtain:
+
+ 2500 * (3767897513/25) ==> 376789751300
+
+Finally we divide with remainder by 10^9 to get:
+
+ val = 376
+ val2 = 789751300
+
+However, we return IIO_VAL_INT_PLUS_MICRO (should have been NANO) as
+the scale type. So when converting the raw temperature value to the
+'processed' temperature value we will get (assuming raw=810,
+offset=-753):
+
+ processed = (raw + offset) * scale_val
+ = (810 + -753) * 376
+ = 21432
+
+ processed += div((raw + offset) * scale_val2, 10^6)
+ += div((810 + -753) * 789751300, 10^6)
+ += 45015
+ ==> 66447
+ ==> 66.4 Celcius
+
+instead of the expected 21.5 Celsius.
+
+Fix this issue by changing IIO_VAL_INT_PLUS_MICRO to
+IIO_VAL_INT_PLUS_NANO.
+
+Fixes: 56ca9db862bf ("iio: dac: Add support for the AD5592R/AD5593R ADCs/DACs")
+Signed-off-by: Marc Ferland <marc.ferland@sonatest.com>
+Link: https://lore.kernel.org/r/20240501150554.1871390-1-marc.ferland@sonatest.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/dac/ad5592r-base.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iio/dac/ad5592r-base.c
++++ b/drivers/iio/dac/ad5592r-base.c
+@@ -415,7 +415,7 @@ static int ad5592r_read_raw(struct iio_d
+ s64 tmp = *val * (3767897513LL / 25LL);
+ *val = div_s64_rem(tmp, 1000000000LL, val2);
+
+- return IIO_VAL_INT_PLUS_MICRO;
++ return IIO_VAL_INT_PLUS_NANO;
+ }
+
+ mutex_lock(&st->lock);
--- /dev/null
+From bedb2ccb566de5ca0c336ca3fd3588cea6d50414 Mon Sep 17 00:00:00 2001
+From: Vasileios Amoiridis <vassilisamir@gmail.com>
+Date: Wed, 8 May 2024 17:54:07 +0200
+Subject: iio: imu: bmi323: Fix trigger notification in case of error
+
+From: Vasileios Amoiridis <vassilisamir@gmail.com>
+
+commit bedb2ccb566de5ca0c336ca3fd3588cea6d50414 upstream.
+
+In case of error in the bmi323_trigger_handler() function, the
+function exits without calling the iio_trigger_notify_done()
+which is responsible for informing the attached trigger that
+the process is done and in case there is a .reenable(), to
+call it.
+
+Fixes: 8a636db3aa57 ("iio: imu: Add driver for BMI323 IMU")
+Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
+Link: https://lore.kernel.org/r/20240508155407.139805-1-vassilisamir@gmail.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/imu/bmi323/bmi323_core.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/iio/imu/bmi323/bmi323_core.c
++++ b/drivers/iio/imu/bmi323/bmi323_core.c
+@@ -1391,7 +1391,7 @@ static irqreturn_t bmi323_trigger_handle
+ &data->buffer.channels,
+ ARRAY_SIZE(data->buffer.channels));
+ if (ret)
+- return IRQ_NONE;
++ goto out;
+ } else {
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ BMI323_CHAN_MAX) {
+@@ -1400,13 +1400,14 @@ static irqreturn_t bmi323_trigger_handle
+ &data->buffer.channels[index++],
+ BMI323_BYTES_PER_SAMPLE);
+ if (ret)
+- return IRQ_NONE;
++ goto out;
+ }
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
+ iio_get_time_ns(indio_dev));
+
++out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
--- /dev/null
+From 245f3b149e6cc3ac6ee612cdb7042263bfc9e73c Mon Sep 17 00:00:00 2001
+From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+Date: Mon, 27 May 2024 21:00:08 +0000
+Subject: iio: imu: inv_icm42600: delete unneeded update watermark call
+
+From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+
+commit 245f3b149e6cc3ac6ee612cdb7042263bfc9e73c upstream.
+
+Update watermark will be done inside the hwfifo_set_watermark callback
+just after the update_scan_mode. It is useless to do it here.
+
+Fixes: 7f85e42a6c54 ("iio: imu: inv_icm42600: add buffer support in iio devices")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+Link: https://lore.kernel.org/r/20240527210008.612932-1-inv.git-commit@tdk.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 4 ----
+ drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 4 ----
+ 2 files changed, 8 deletions(-)
+
+--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+@@ -129,10 +129,6 @@ static int inv_icm42600_accel_update_sca
+ /* update data FIFO write */
+ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
+ ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
+- if (ret)
+- goto out_unlock;
+-
+- ret = inv_icm42600_buffer_update_watermark(st);
+
+ out_unlock:
+ mutex_unlock(&st->lock);
+--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
++++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+@@ -129,10 +129,6 @@ static int inv_icm42600_gyro_update_scan
+ /* update data FIFO write */
+ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
+ ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
+- if (ret)
+- goto out_unlock;
+-
+- ret = inv_icm42600_buffer_update_watermark(st);
+
+ out_unlock:
+ mutex_unlock(&st->lock);
--- /dev/null
+From 95444b9eeb8c5c0330563931d70c61ca3b101548 Mon Sep 17 00:00:00 2001
+From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+Date: Fri, 24 May 2024 12:48:51 +0000
+Subject: iio: invensense: fix odr switching to same value
+
+From: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+
+commit 95444b9eeb8c5c0330563931d70c61ca3b101548 upstream.
+
+ODR switching happens in 2 steps, update to store the new value and then
+apply when the ODR change flag is received in the data. When switching to
+the same ODR value, the ODR change flag is never happening, and frequency
+switching is blocked waiting for the never coming apply.
+
+Fix the issue by preventing update to happen when switching to same ODR
+value.
+
+Fixes: 0ecc363ccea7 ("iio: make invensense timestamp module generic")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+Link: https://lore.kernel.org/r/20240524124851.567485-1-inv.git-commit@tdk.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
++++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
+@@ -60,11 +60,15 @@ EXPORT_SYMBOL_NS_GPL(inv_sensors_timesta
+ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
+ uint32_t period, bool fifo)
+ {
++ uint32_t mult;
++
+ /* when FIFO is on, prevent odr change if one is already pending */
+ if (fifo && ts->new_mult != 0)
+ return -EAGAIN;
+
+- ts->new_mult = period / ts->chip.clock_period;
++ mult = period / ts->chip.clock_period;
++ if (mult != ts->mult)
++ ts->new_mult = mult;
+
+ return 0;
+ }
--- /dev/null
+From 0f0f6306617cb4b6231fc9d4ec68ab9a56dba7c0 Mon Sep 17 00:00:00 2001
+From: Adam Rizkalla <ajarizzo@gmail.com>
+Date: Thu, 25 Apr 2024 01:22:49 -0500
+Subject: iio: pressure: bmp280: Fix BMP580 temperature reading
+
+From: Adam Rizkalla <ajarizzo@gmail.com>
+
+commit 0f0f6306617cb4b6231fc9d4ec68ab9a56dba7c0 upstream.
+
+Fix overflow issue when storing BMP580 temperature reading and
+properly preserve sign of 24-bit data.
+
+Signed-off-by: Adam Rizkalla <ajarizzo@gmail.com>
+Tested-By: Vasileios Amoiridis <vassilisamir@gmail.com>
+Acked-by: Angel Iglesias <ang.iglesiasg@gmail.com>
+Link: https://lore.kernel.org/r/Zin2udkXRD0+GrML@adam-asahi.lan
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/pressure/bmp280-core.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/iio/pressure/bmp280-core.c
++++ b/drivers/iio/pressure/bmp280-core.c
+@@ -1394,12 +1394,12 @@ static int bmp580_read_temp(struct bmp28
+
+ /*
+ * Temperature is returned in Celsius degrees in fractional
+- * form down 2^16. We rescale by x1000 to return milli Celsius
+- * to respect IIO ABI.
++ * form down 2^16. We rescale by x1000 to return millidegrees
++ * Celsius to respect IIO ABI.
+ */
+- *val = raw_temp * 1000;
+- *val2 = 16;
+- return IIO_VAL_FRACTIONAL_LOG2;
++ raw_temp = sign_extend32(raw_temp, 23);
++ *val = ((s64)raw_temp * 1000) / (1 << 16);
++ return IIO_VAL_INT;
+ }
+
+ static int bmp580_read_press(struct bmp280_data *data, int *val, int *val2)
--- /dev/null
+From a23c14b062d8800a2192077d83273bbfe6c7552d Mon Sep 17 00:00:00 2001
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Date: Mon, 13 May 2024 13:34:27 -0700
+Subject: iio: temperature: mlx90635: Fix ERR_PTR dereference in mlx90635_probe()
+
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+
+commit a23c14b062d8800a2192077d83273bbfe6c7552d upstream.
+
+When devm_regmap_init_i2c() fails, regmap_ee could be error pointer,
+instead of checking for IS_ERR(regmap_ee), regmap is checked which looks
+like a copy paste error.
+
+Fixes: a1d1ba5e1c28 ("iio: temperature: mlx90635 MLX90635 IR Temperature sensor")
+Reviewed-by: Crt Mori<cmo@melexis.com>
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Link: https://lore.kernel.org/r/20240513203427.3208696-1-harshit.m.mogalapalli@oracle.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/temperature/mlx90635.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/iio/temperature/mlx90635.c
++++ b/drivers/iio/temperature/mlx90635.c
+@@ -947,9 +947,9 @@ static int mlx90635_probe(struct i2c_cli
+ "failed to allocate regmap\n");
+
+ regmap_ee = devm_regmap_init_i2c(client, &mlx90635_regmap_ee);
+- if (IS_ERR(regmap))
+- return dev_err_probe(&client->dev, PTR_ERR(regmap),
+- "failed to allocate regmap\n");
++ if (IS_ERR(regmap_ee))
++ return dev_err_probe(&client->dev, PTR_ERR(regmap_ee),
++ "failed to allocate EEPROM regmap\n");
+
+ mlx90635 = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
--- /dev/null
+From 2bfc4214c69c62da13a9da8e3c3db5539da2ccd3 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Tue, 11 Jun 2024 23:27:27 +0900
+Subject: ksmbd: fix missing use of get_write in in smb2_set_ea()
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 2bfc4214c69c62da13a9da8e3c3db5539da2ccd3 upstream.
+
+Fix an issue where get_write is not used in smb2_set_ea().
+
+Fixes: 6fc0a265e1b9 ("ksmbd: fix potential circular locking issue in smb2_set_ea()")
+Cc: stable@vger.kernel.org
+Reported-by: Wang Zhaolong <wangzhaolong1@huawei.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smb2pdu.c | 7 ++++---
+ fs/smb/server/vfs.c | 17 +++++++++++------
+ fs/smb/server/vfs.h | 3 ++-
+ fs/smb/server/vfs_cache.c | 3 ++-
+ 4 files changed, 19 insertions(+), 11 deletions(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -2367,7 +2367,8 @@ static int smb2_set_ea(struct smb2_ea_in
+ if (rc > 0) {
+ rc = ksmbd_vfs_remove_xattr(idmap,
+ path,
+- attr_name);
++ attr_name,
++ get_write);
+
+ if (rc < 0) {
+ ksmbd_debug(SMB,
+@@ -2382,7 +2383,7 @@ static int smb2_set_ea(struct smb2_ea_in
+ } else {
+ rc = ksmbd_vfs_setxattr(idmap, path, attr_name, value,
+ le16_to_cpu(eabuf->EaValueLength),
+- 0, true);
++ 0, get_write);
+ if (rc < 0) {
+ ksmbd_debug(SMB,
+ "ksmbd_vfs_setxattr is failed(%d)\n",
+@@ -2474,7 +2475,7 @@ static int smb2_remove_smb_xattrs(const
+ !strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX,
+ STREAM_PREFIX_LEN)) {
+ err = ksmbd_vfs_remove_xattr(idmap, path,
+- name);
++ name, true);
+ if (err)
+ ksmbd_debug(SMB, "remove xattr failed : %s\n",
+ name);
+--- a/fs/smb/server/vfs.c
++++ b/fs/smb/server/vfs.c
+@@ -1058,16 +1058,21 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_fi
+ }
+
+ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
+- const struct path *path, char *attr_name)
++ const struct path *path, char *attr_name,
++ bool get_write)
+ {
+ int err;
+
+- err = mnt_want_write(path->mnt);
+- if (err)
+- return err;
++ if (get_write == true) {
++ err = mnt_want_write(path->mnt);
++ if (err)
++ return err;
++ }
+
+ err = vfs_removexattr(idmap, path->dentry, attr_name);
+- mnt_drop_write(path->mnt);
++
++ if (get_write == true)
++ mnt_drop_write(path->mnt);
+
+ return err;
+ }
+@@ -1380,7 +1385,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct mn
+ ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
+
+ if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
+- err = ksmbd_vfs_remove_xattr(idmap, path, name);
++ err = ksmbd_vfs_remove_xattr(idmap, path, name, true);
+ if (err)
+ ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
+ }
+--- a/fs/smb/server/vfs.h
++++ b/fs/smb/server/vfs.h
+@@ -114,7 +114,8 @@ int ksmbd_vfs_setxattr(struct mnt_idmap
+ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
+ size_t *xattr_stream_name_size, int s_type);
+ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
+- const struct path *path, char *attr_name);
++ const struct path *path, char *attr_name,
++ bool get_write);
+ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
+ unsigned int flags, struct path *parent_path,
+ struct path *path, bool caseless);
+--- a/fs/smb/server/vfs_cache.c
++++ b/fs/smb/server/vfs_cache.c
+@@ -254,7 +254,8 @@ static void __ksmbd_inode_close(struct k
+ ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
+ err = ksmbd_vfs_remove_xattr(file_mnt_idmap(filp),
+ &filp->f_path,
+- fp->stream.name);
++ fp->stream.name,
++ true);
+ if (err)
+ pr_err("remove xattr failed : %s\n",
+ fp->stream.name);
--- /dev/null
+From 1cdeca6a7264021e20157de0baf7880ff0ced822 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Mon, 10 Jun 2024 23:06:19 +0900
+Subject: ksmbd: move leading slash check to smb2_get_name()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 1cdeca6a7264021e20157de0baf7880ff0ced822 upstream.
+
+If the directory name in the root of the share starts with
+character like 镜(0x955c) or Ṝ(0x1e5c), it (and anything inside)
+cannot be accessed. The leading slash check must be checked after
+converting unicode to nls string.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smb2pdu.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -630,6 +630,12 @@ smb2_get_name(const char *src, const int
+ return name;
+ }
+
++ if (*name == '\\') {
++ pr_err("not allow directory name included leading slash\n");
++ kfree(name);
++ return ERR_PTR(-EINVAL);
++ }
++
+ ksmbd_conv_path_to_unix(name);
+ ksmbd_strip_last_slash(name);
+ return name;
+@@ -2842,20 +2848,11 @@ int smb2_open(struct ksmbd_work *work)
+ }
+
+ if (req->NameLength) {
+- if ((req->CreateOptions & FILE_DIRECTORY_FILE_LE) &&
+- *(char *)req->Buffer == '\\') {
+- pr_err("not allow directory name included leading slash\n");
+- rc = -EINVAL;
+- goto err_out2;
+- }
+-
+ name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset),
+ le16_to_cpu(req->NameLength),
+ work->conn->local_nls);
+ if (IS_ERR(name)) {
+ rc = PTR_ERR(name);
+- if (rc != -ENOMEM)
+- rc = -ENOENT;
+ name = NULL;
+ goto err_out2;
+ }
--- /dev/null
+From fcf2a9970ef587d8f358560c381ee6115a9108aa Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Fri, 7 Jun 2024 12:18:47 +0200
+Subject: leds: class: Revert: "If no default trigger is given, make hw_control trigger the default trigger"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit fcf2a9970ef587d8f358560c381ee6115a9108aa upstream.
+
+Commit 66601a29bb23 ("leds: class: If no default trigger is given, make
+hw_control trigger the default trigger") causes ledtrig-netdev to get
+set as default trigger on various network LEDs.
+
+This causes users to hit a pre-existing AB-BA deadlock issue in
+ledtrig-netdev between the LED-trigger locks and the rtnl mutex,
+resulting in hung tasks in kernels >= 6.9.
+
+Solving the deadlock is non trivial, so for now revert the change to
+set the hw_control trigger as default trigger, so that ledtrig-netdev
+no longer gets activated automatically for various network LEDs.
+
+The netdev trigger is not needed because the network LEDs are usually under
+hw-control and the netdev trigger tries to leave things that way so setting
+it as the active trigger for the LED class device is a no-op.
+
+Fixes: 66601a29bb23 ("leds: class: If no default trigger is given, make hw_control trigger the default trigger")
+Reported-by: Genes Lists <lists@sapience.com>
+Closes: https://lore.kernel.org/all/9d189ec329cfe68ed68699f314e191a10d4b5eda.camel@sapience.com/
+Reported-by: Johannes Wüller <johanneswueller@gmail.com>
+Closes: https://lore.kernel.org/lkml/e441605c-eaf2-4c2d-872b-d8e541f4cf60@gmail.com/
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Acked-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/leds/led-class.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
+index 24fcff682b24..ba1be15cfd8e 100644
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -552,12 +552,6 @@ int led_classdev_register_ext(struct device *parent,
+ led_init_core(led_cdev);
+
+ #ifdef CONFIG_LEDS_TRIGGERS
+- /*
+- * If no default trigger was given and hw_control_trigger is set,
+- * make it the default trigger.
+- */
+- if (!led_cdev->default_trigger && led_cdev->hw_control_trigger)
+- led_cdev->default_trigger = led_cdev->hw_control_trigger;
+ led_trigger_set_default(led_cdev);
+ #endif
+
+--
+2.45.2
+
--- /dev/null
+From 086c6cbcc563c81d55257f9b27e14faf1d0963d3 Mon Sep 17 00:00:00 2001
+From: Yongzhi Liu <hyperlyzcs@gmail.com>
+Date: Thu, 23 May 2024 20:14:33 +0800
+Subject: misc: microchip: pci1xxxx: fix double free in the error handling of gp_aux_bus_probe()
+
+From: Yongzhi Liu <hyperlyzcs@gmail.com>
+
+commit 086c6cbcc563c81d55257f9b27e14faf1d0963d3 upstream.
+
+When auxiliary_device_add() returns error and then calls
+auxiliary_device_uninit(), callback function
+gp_auxiliary_device_release() calls ida_free() and
+kfree(aux_device_wrapper) to free memory. We should't
+call them again in the error handling path.
+
+Fix this by skipping the redundant cleanup functions.
+
+Fixes: 393fc2f5948f ("misc: microchip: pci1xxxx: load auxiliary bus driver for the PIO function in the multi-function endpoint of pci1xxxx device.")
+Signed-off-by: Yongzhi Liu <hyperlyzcs@gmail.com>
+Link: https://lore.kernel.org/r/20240523121434.21855-3-hyperlyzcs@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c
++++ b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c
+@@ -111,6 +111,7 @@ static int gp_aux_bus_probe(struct pci_d
+
+ err_aux_dev_add_1:
+ auxiliary_device_uninit(&aux_bus->aux_device_wrapper[1]->aux_dev);
++ goto err_aux_dev_add_0;
+
+ err_aux_dev_init_1:
+ ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[1]->aux_dev.id);
+@@ -120,6 +121,7 @@ err_ida_alloc_1:
+
+ err_aux_dev_add_0:
+ auxiliary_device_uninit(&aux_bus->aux_device_wrapper[0]->aux_dev);
++ goto err_ret;
+
+ err_aux_dev_init_0:
+ ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[0]->aux_dev.id);
+@@ -127,6 +129,7 @@ err_aux_dev_init_0:
+ err_ida_alloc_0:
+ kfree(aux_bus->aux_device_wrapper[0]);
+
++err_ret:
+ return retval;
+ }
+
--- /dev/null
+From 72d95924ee35c8cd16ef52f912483ee938a34d49 Mon Sep 17 00:00:00 2001
+From: John David Anglin <dave@parisc-linux.org>
+Date: Mon, 10 Jun 2024 18:47:07 +0000
+Subject: parisc: Try to fix random segmentation faults in package builds
+
+From: John David Anglin <dave@parisc-linux.org>
+
+commit 72d95924ee35c8cd16ef52f912483ee938a34d49 upstream.
+
+PA-RISC systems with PA8800 and PA8900 processors have had problems
+with random segmentation faults for many years. Systems with earlier
+processors are much more stable.
+
+Systems with PA8800 and PA8900 processors have a large L2 cache which
+needs per page flushing for decent performance when a large range is
+flushed. The combined cache in these systems is also more sensitive to
+non-equivalent aliases than the caches in earlier systems.
+
+The majority of random segmentation faults that I have looked at
+appear to be memory corruption in memory allocated using mmap and
+malloc.
+
+My first attempt at fixing the random faults didn't work. On
+reviewing the cache code, I realized that there were two issues
+which the existing code didn't handle correctly. Both relate
+to cache move-in. Another issue is that the present bit in PTEs
+is racy.
+
+1) PA-RISC caches have a mind of their own and they can speculatively
+load data and instructions for a page as long as there is a entry in
+the TLB for the page which allows move-in. TLBs are local to each
+CPU. Thus, the TLB entry for a page must be purged before flushing
+the page. This is particularly important on SMP systems.
+
+In some of the flush routines, the flush routine would be called
+and then the TLB entry would be purged. This was because the flush
+routine needed the TLB entry to do the flush.
+
+2) My initial approach to trying the fix the random faults was to
+try and use flush_cache_page_if_present for all flush operations.
+This actually made things worse and led to a couple of hardware
+lockups. It finally dawned on me that some lines weren't being
+flushed because the pte check code was racy. This resulted in
+random inequivalent mappings to physical pages.
+
+The __flush_cache_page tmpalias flush sets up its own TLB entry
+and it doesn't need the existing TLB entry. As long as we can find
+the pte pointer for the vm page, we can get the pfn and physical
+address of the page. We can also purge the TLB entry for the page
+before doing the flush. Further, __flush_cache_page uses a special
+TLB entry that inhibits cache move-in.
+
+When switching page mappings, we need to ensure that lines are
+removed from the cache. It is not sufficient to just flush the
+lines to memory as they may come back.
+
+This made it clear that we needed to implement all the required
+flush operations using tmpalias routines. This includes flushes
+for user and kernel pages.
+
+After modifying the code to use tmpalias flushes, it became clear
+that the random segmentation faults were not fully resolved. The
+frequency of faults was worse on systems with a 64 MB L2 (PA8900)
+and systems with more CPUs (rp4440).
+
+The warning that I added to flush_cache_page_if_present to detect
+pages that couldn't be flushed triggered frequently on some systems.
+
+Helge and I looked at the pages that couldn't be flushed and found
+that the PTE was either cleared or for a swap page. Ignoring pages
+that were swapped out seemed okay but pages with cleared PTEs seemed
+problematic.
+
+I looked at routines related to pte_clear and noticed ptep_clear_flush.
+The default implementation just flushes the TLB entry. However, it was
+obvious that on parisc we need to flush the cache page as well. If
+we don't flush the cache page, stale lines will be left in the cache
+and cause random corruption. Once a PTE is cleared, there is no way
+to find the physical address associated with the PTE and flush the
+associated page at a later time.
+
+I implemented an updated change with a parisc specific version of
+ptep_clear_flush. It fixed the random data corruption on Helge's rp4440
+and rp3440, as well as on my c8000.
+
+At this point, I realized that I could restore the code where we only
+flush in flush_cache_page_if_present if the page has been accessed.
+However, for this, we also need to flush the cache when the accessed
+bit is cleared in ptep_clear_flush_young to keep things synchronized.
+The default implementation only flushes the TLB entry.
+
+Other changes in this version are:
+
+1) Implement parisc specific version of ptep_get. It's identical to
+default but needed in arch/parisc/include/asm/pgtable.h.
+2) Revise parisc implementation of ptep_test_and_clear_young to use
+ptep_get (READ_ONCE).
+3) Drop parisc implementation of ptep_get_and_clear. We can use default.
+4) Revise flush_kernel_vmap_range and invalidate_kernel_vmap_range to
+use full data cache flush.
+5) Move flush_cache_vmap and flush_cache_vunmap to cache.c. Handle
+VM_IOREMAP case in flush_cache_vmap.
+
+At this time, I don't know whether it is better to always flush when
+the PTE present bit is set or when both the accessed and present bits
+are set. The later saves flushing pages that haven't been accessed,
+but we need to flush in ptep_clear_flush_young. It also needs a page
+table lookup to find the PTE pointer. The lpa instruction only needs
+a page table lookup when the PTE entry isn't in the TLB.
+
+We don't atomically handle setting and clearing the _PAGE_ACCESSED bit.
+If we miss an update, we may miss a flush and the cache may get corrupted.
+Whether the current code is effectively atomic depends on process control.
+
+When CONFIG_FLUSH_PAGE_ACCESSED is set to zero, the page will eventually
+be flushed when the PTE is cleared or in flush_cache_page_if_present. The
+_PAGE_ACCESSED bit is not used, so the problem is avoided.
+
+The flush method can be selected using the CONFIG_FLUSH_PAGE_ACCESSED
+define in cache.c. The default is 0. I didn't see a large difference
+in performance.
+
+Signed-off-by: John David Anglin <dave.anglin@bell.net>
+Cc: <stable@vger.kernel.org> # v6.6+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/parisc/include/asm/cacheflush.h | 15 -
+ arch/parisc/include/asm/pgtable.h | 27 +-
+ arch/parisc/kernel/cache.c | 411 +++++++++++++++++++++--------------
+ 3 files changed, 274 insertions(+), 179 deletions(-)
+
+--- a/arch/parisc/include/asm/cacheflush.h
++++ b/arch/parisc/include/asm/cacheflush.h
+@@ -31,18 +31,17 @@ void flush_cache_all_local(void);
+ void flush_cache_all(void);
+ void flush_cache_mm(struct mm_struct *mm);
+
+-void flush_kernel_dcache_page_addr(const void *addr);
+-
+ #define flush_kernel_dcache_range(start,size) \
+ flush_kernel_dcache_range_asm((start), (start)+(size));
+
++/* The only way to flush a vmap range is to flush whole cache */
+ #define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
+ void flush_kernel_vmap_range(void *vaddr, int size);
+ void invalidate_kernel_vmap_range(void *vaddr, int size);
+
+-#define flush_cache_vmap(start, end) flush_cache_all()
++void flush_cache_vmap(unsigned long start, unsigned long end);
+ #define flush_cache_vmap_early(start, end) do { } while (0)
+-#define flush_cache_vunmap(start, end) flush_cache_all()
++void flush_cache_vunmap(unsigned long start, unsigned long end);
+
+ void flush_dcache_folio(struct folio *folio);
+ #define flush_dcache_folio flush_dcache_folio
+@@ -77,17 +76,11 @@ void flush_cache_page(struct vm_area_str
+ void flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+
+-/* defined in pacache.S exported in cache.c used by flush_anon_page */
+-void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+-
+ #define ARCH_HAS_FLUSH_ANON_PAGE
+ void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr);
+
+ #define ARCH_HAS_FLUSH_ON_KUNMAP
+-static inline void kunmap_flush_on_unmap(const void *addr)
+-{
+- flush_kernel_dcache_page_addr(addr);
+-}
++void kunmap_flush_on_unmap(const void *addr);
+
+ #endif /* _PARISC_CACHEFLUSH_H */
+
+--- a/arch/parisc/include/asm/pgtable.h
++++ b/arch/parisc/include/asm/pgtable.h
+@@ -448,14 +448,17 @@ static inline pte_t pte_swp_clear_exclus
+ return pte;
+ }
+
++static inline pte_t ptep_get(pte_t *ptep)
++{
++ return READ_ONCE(*ptep);
++}
++#define ptep_get ptep_get
++
+ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+ {
+ pte_t pte;
+
+- if (!pte_young(*ptep))
+- return 0;
+-
+- pte = *ptep;
++ pte = ptep_get(ptep);
+ if (!pte_young(pte)) {
+ return 0;
+ }
+@@ -463,17 +466,10 @@ static inline int ptep_test_and_clear_yo
+ return 1;
+ }
+
+-struct mm_struct;
+-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+-{
+- pte_t old_pte;
+-
+- old_pte = *ptep;
+- set_pte(ptep, __pte(0));
+-
+- return old_pte;
+-}
++int ptep_clear_flush_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep);
++pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep);
+
++struct mm_struct;
+ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+ {
+ set_pte(ptep, pte_wrprotect(*ptep));
+@@ -511,7 +507,8 @@ static inline void ptep_set_wrprotect(st
+ #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
+ #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
++#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
++#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
+ #define __HAVE_ARCH_PTEP_SET_WRPROTECT
+ #define __HAVE_ARCH_PTE_SAME
+
+--- a/arch/parisc/kernel/cache.c
++++ b/arch/parisc/kernel/cache.c
+@@ -20,6 +20,7 @@
+ #include <linux/sched.h>
+ #include <linux/sched/mm.h>
+ #include <linux/syscalls.h>
++#include <linux/vmalloc.h>
+ #include <asm/pdc.h>
+ #include <asm/cache.h>
+ #include <asm/cacheflush.h>
+@@ -31,20 +32,31 @@
+ #include <asm/mmu_context.h>
+ #include <asm/cachectl.h>
+
++#define PTR_PAGE_ALIGN_DOWN(addr) PTR_ALIGN_DOWN(addr, PAGE_SIZE)
++
++/*
++ * When nonzero, use _PAGE_ACCESSED bit to try to reduce the number
++ * of page flushes done flush_cache_page_if_present. There are some
++ * pros and cons in using this option. It may increase the risk of
++ * random segmentation faults.
++ */
++#define CONFIG_FLUSH_PAGE_ACCESSED 0
++
+ int split_tlb __ro_after_init;
+ int dcache_stride __ro_after_init;
+ int icache_stride __ro_after_init;
+ EXPORT_SYMBOL(dcache_stride);
+
++/* Internal implementation in arch/parisc/kernel/pacache.S */
+ void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+ EXPORT_SYMBOL(flush_dcache_page_asm);
+ void purge_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+ void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+-
+-/* Internal implementation in arch/parisc/kernel/pacache.S */
+ void flush_data_cache_local(void *); /* flushes local data-cache only */
+ void flush_instruction_cache_local(void); /* flushes local code-cache only */
+
++static void flush_kernel_dcache_page_addr(const void *addr);
++
+ /* On some machines (i.e., ones with the Merced bus), there can be
+ * only a single PxTLB broadcast at a time; this must be guaranteed
+ * by software. We need a spinlock around all TLB flushes to ensure
+@@ -321,6 +333,18 @@ __flush_cache_page(struct vm_area_struct
+ {
+ if (!static_branch_likely(&parisc_has_cache))
+ return;
++
++ /*
++ * The TLB is the engine of coherence on parisc. The CPU is
++ * entitled to speculate any page with a TLB mapping, so here
++ * we kill the mapping then flush the page along a special flush
++ * only alias mapping. This guarantees that the page is no-longer
++ * in the cache for any process and nor may it be speculatively
++ * read in (until the user or kernel specifically accesses it,
++ * of course).
++ */
++ flush_tlb_page(vma, vmaddr);
++
+ preempt_disable();
+ flush_dcache_page_asm(physaddr, vmaddr);
+ if (vma->vm_flags & VM_EXEC)
+@@ -328,46 +352,44 @@ __flush_cache_page(struct vm_area_struct
+ preempt_enable();
+ }
+
+-static void flush_user_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
++static void flush_kernel_dcache_page_addr(const void *addr)
+ {
+- unsigned long flags, space, pgd, prot;
+-#ifdef CONFIG_TLB_PTLOCK
+- unsigned long pgd_lock;
+-#endif
++ unsigned long vaddr = (unsigned long)addr;
++ unsigned long flags;
+
+- vmaddr &= PAGE_MASK;
++ /* Purge TLB entry to remove translation on all CPUs */
++ purge_tlb_start(flags);
++ pdtlb(SR_KERNEL, addr);
++ purge_tlb_end(flags);
+
++ /* Use tmpalias flush to prevent data cache move-in */
+ preempt_disable();
++ flush_dcache_page_asm(__pa(vaddr), vaddr);
++ preempt_enable();
++}
+
+- /* Set context for flush */
+- local_irq_save(flags);
+- prot = mfctl(8);
+- space = mfsp(SR_USER);
+- pgd = mfctl(25);
+-#ifdef CONFIG_TLB_PTLOCK
+- pgd_lock = mfctl(28);
+-#endif
+- switch_mm_irqs_off(NULL, vma->vm_mm, NULL);
+- local_irq_restore(flags);
+-
+- flush_user_dcache_range_asm(vmaddr, vmaddr + PAGE_SIZE);
+- if (vma->vm_flags & VM_EXEC)
+- flush_user_icache_range_asm(vmaddr, vmaddr + PAGE_SIZE);
+- flush_tlb_page(vma, vmaddr);
++static void flush_kernel_icache_page_addr(const void *addr)
++{
++ unsigned long vaddr = (unsigned long)addr;
++ unsigned long flags;
+
+- /* Restore previous context */
+- local_irq_save(flags);
+-#ifdef CONFIG_TLB_PTLOCK
+- mtctl(pgd_lock, 28);
+-#endif
+- mtctl(pgd, 25);
+- mtsp(space, SR_USER);
+- mtctl(prot, 8);
+- local_irq_restore(flags);
++ /* Purge TLB entry to remove translation on all CPUs */
++ purge_tlb_start(flags);
++ pdtlb(SR_KERNEL, addr);
++ purge_tlb_end(flags);
+
++ /* Use tmpalias flush to prevent instruction cache move-in */
++ preempt_disable();
++ flush_icache_page_asm(__pa(vaddr), vaddr);
+ preempt_enable();
+ }
+
++void kunmap_flush_on_unmap(const void *addr)
++{
++ flush_kernel_dcache_page_addr(addr);
++}
++EXPORT_SYMBOL(kunmap_flush_on_unmap);
++
+ void flush_icache_pages(struct vm_area_struct *vma, struct page *page,
+ unsigned int nr)
+ {
+@@ -375,13 +397,16 @@ void flush_icache_pages(struct vm_area_s
+
+ for (;;) {
+ flush_kernel_dcache_page_addr(kaddr);
+- flush_kernel_icache_page(kaddr);
++ flush_kernel_icache_page_addr(kaddr);
+ if (--nr == 0)
+ break;
+ kaddr += PAGE_SIZE;
+ }
+ }
+
++/*
++ * Walk page directory for MM to find PTEP pointer for address ADDR.
++ */
+ static inline pte_t *get_ptep(struct mm_struct *mm, unsigned long addr)
+ {
+ pte_t *ptep = NULL;
+@@ -410,6 +435,41 @@ static inline bool pte_needs_flush(pte_t
+ == (_PAGE_PRESENT | _PAGE_ACCESSED);
+ }
+
++/*
++ * Return user physical address. Returns 0 if page is not present.
++ */
++static inline unsigned long get_upa(struct mm_struct *mm, unsigned long addr)
++{
++ unsigned long flags, space, pgd, prot, pa;
++#ifdef CONFIG_TLB_PTLOCK
++ unsigned long pgd_lock;
++#endif
++
++ /* Save context */
++ local_irq_save(flags);
++ prot = mfctl(8);
++ space = mfsp(SR_USER);
++ pgd = mfctl(25);
++#ifdef CONFIG_TLB_PTLOCK
++ pgd_lock = mfctl(28);
++#endif
++
++ /* Set context for lpa_user */
++ switch_mm_irqs_off(NULL, mm, NULL);
++ pa = lpa_user(addr);
++
++ /* Restore previous context */
++#ifdef CONFIG_TLB_PTLOCK
++ mtctl(pgd_lock, 28);
++#endif
++ mtctl(pgd, 25);
++ mtsp(space, SR_USER);
++ mtctl(prot, 8);
++ local_irq_restore(flags);
++
++ return pa;
++}
++
+ void flush_dcache_folio(struct folio *folio)
+ {
+ struct address_space *mapping = folio_flush_mapping(folio);
+@@ -458,50 +518,23 @@ void flush_dcache_folio(struct folio *fo
+ if (addr + nr * PAGE_SIZE > vma->vm_end)
+ nr = (vma->vm_end - addr) / PAGE_SIZE;
+
+- if (parisc_requires_coherency()) {
+- for (i = 0; i < nr; i++) {
+- pte_t *ptep = get_ptep(vma->vm_mm,
+- addr + i * PAGE_SIZE);
+- if (!ptep)
+- continue;
+- if (pte_needs_flush(*ptep))
+- flush_user_cache_page(vma,
+- addr + i * PAGE_SIZE);
+- /* Optimise accesses to the same table? */
+- pte_unmap(ptep);
+- }
+- } else {
++ if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
++ != (addr & (SHM_COLOUR - 1))) {
++ for (i = 0; i < nr; i++)
++ __flush_cache_page(vma,
++ addr + i * PAGE_SIZE,
++ (pfn + i) * PAGE_SIZE);
+ /*
+- * The TLB is the engine of coherence on parisc:
+- * The CPU is entitled to speculate any page
+- * with a TLB mapping, so here we kill the
+- * mapping then flush the page along a special
+- * flush only alias mapping. This guarantees that
+- * the page is no-longer in the cache for any
+- * process and nor may it be speculatively read
+- * in (until the user or kernel specifically
+- * accesses it, of course)
++ * Software is allowed to have any number
++ * of private mappings to a page.
+ */
+- for (i = 0; i < nr; i++)
+- flush_tlb_page(vma, addr + i * PAGE_SIZE);
+- if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1))
+- != (addr & (SHM_COLOUR - 1))) {
+- for (i = 0; i < nr; i++)
+- __flush_cache_page(vma,
+- addr + i * PAGE_SIZE,
+- (pfn + i) * PAGE_SIZE);
+- /*
+- * Software is allowed to have any number
+- * of private mappings to a page.
+- */
+- if (!(vma->vm_flags & VM_SHARED))
+- continue;
+- if (old_addr)
+- pr_err("INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %pD\n",
+- old_addr, addr, vma->vm_file);
+- if (nr == folio_nr_pages(folio))
+- old_addr = addr;
+- }
++ if (!(vma->vm_flags & VM_SHARED))
++ continue;
++ if (old_addr)
++ pr_err("INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %pD\n",
++ old_addr, addr, vma->vm_file);
++ if (nr == folio_nr_pages(folio))
++ old_addr = addr;
+ }
+ WARN_ON(++count == 4096);
+ }
+@@ -591,35 +624,28 @@ extern void purge_kernel_dcache_page_asm
+ extern void clear_user_page_asm(void *, unsigned long);
+ extern void copy_user_page_asm(void *, void *, unsigned long);
+
+-void flush_kernel_dcache_page_addr(const void *addr)
+-{
+- unsigned long flags;
+-
+- flush_kernel_dcache_page_asm(addr);
+- purge_tlb_start(flags);
+- pdtlb(SR_KERNEL, addr);
+- purge_tlb_end(flags);
+-}
+-EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
+-
+ static void flush_cache_page_if_present(struct vm_area_struct *vma,
+- unsigned long vmaddr, unsigned long pfn)
++ unsigned long vmaddr)
+ {
++#if CONFIG_FLUSH_PAGE_ACCESSED
+ bool needs_flush = false;
+- pte_t *ptep;
++ pte_t *ptep, pte;
+
+- /*
+- * The pte check is racy and sometimes the flush will trigger
+- * a non-access TLB miss. Hopefully, the page has already been
+- * flushed.
+- */
+ ptep = get_ptep(vma->vm_mm, vmaddr);
+ if (ptep) {
+- needs_flush = pte_needs_flush(*ptep);
++ pte = ptep_get(ptep);
++ needs_flush = pte_needs_flush(pte);
+ pte_unmap(ptep);
+ }
+ if (needs_flush)
+- flush_cache_page(vma, vmaddr, pfn);
++ __flush_cache_page(vma, vmaddr, PFN_PHYS(pte_pfn(pte)));
++#else
++ struct mm_struct *mm = vma->vm_mm;
++ unsigned long physaddr = get_upa(mm, vmaddr);
++
++ if (physaddr)
++ __flush_cache_page(vma, vmaddr, PAGE_ALIGN_DOWN(physaddr));
++#endif
+ }
+
+ void copy_user_highpage(struct page *to, struct page *from,
+@@ -629,7 +655,7 @@ void copy_user_highpage(struct page *to,
+
+ kfrom = kmap_local_page(from);
+ kto = kmap_local_page(to);
+- flush_cache_page_if_present(vma, vaddr, page_to_pfn(from));
++ __flush_cache_page(vma, vaddr, PFN_PHYS(page_to_pfn(from)));
+ copy_page_asm(kto, kfrom);
+ kunmap_local(kto);
+ kunmap_local(kfrom);
+@@ -638,16 +664,17 @@ void copy_user_highpage(struct page *to,
+ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+ unsigned long user_vaddr, void *dst, void *src, int len)
+ {
+- flush_cache_page_if_present(vma, user_vaddr, page_to_pfn(page));
++ __flush_cache_page(vma, user_vaddr, PFN_PHYS(page_to_pfn(page)));
+ memcpy(dst, src, len);
+- flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len);
++ flush_kernel_dcache_page_addr(PTR_PAGE_ALIGN_DOWN(dst));
+ }
+
+ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+ unsigned long user_vaddr, void *dst, void *src, int len)
+ {
+- flush_cache_page_if_present(vma, user_vaddr, page_to_pfn(page));
++ __flush_cache_page(vma, user_vaddr, PFN_PHYS(page_to_pfn(page)));
+ memcpy(dst, src, len);
++ flush_kernel_dcache_page_addr(PTR_PAGE_ALIGN_DOWN(src));
+ }
+
+ /* __flush_tlb_range()
+@@ -681,32 +708,10 @@ int __flush_tlb_range(unsigned long sid,
+
+ static void flush_cache_pages(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+ {
+- unsigned long addr, pfn;
+- pte_t *ptep;
++ unsigned long addr;
+
+- for (addr = start; addr < end; addr += PAGE_SIZE) {
+- bool needs_flush = false;
+- /*
+- * The vma can contain pages that aren't present. Although
+- * the pte search is expensive, we need the pte to find the
+- * page pfn and to check whether the page should be flushed.
+- */
+- ptep = get_ptep(vma->vm_mm, addr);
+- if (ptep) {
+- needs_flush = pte_needs_flush(*ptep);
+- pfn = pte_pfn(*ptep);
+- pte_unmap(ptep);
+- }
+- if (needs_flush) {
+- if (parisc_requires_coherency()) {
+- flush_user_cache_page(vma, addr);
+- } else {
+- if (WARN_ON(!pfn_valid(pfn)))
+- return;
+- __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+- }
+- }
+- }
++ for (addr = start; addr < end; addr += PAGE_SIZE)
++ flush_cache_page_if_present(vma, addr);
+ }
+
+ static inline unsigned long mm_total_size(struct mm_struct *mm)
+@@ -757,21 +762,19 @@ void flush_cache_range(struct vm_area_st
+ if (WARN_ON(IS_ENABLED(CONFIG_SMP) && arch_irqs_disabled()))
+ return;
+ flush_tlb_range(vma, start, end);
+- flush_cache_all();
++ if (vma->vm_flags & VM_EXEC)
++ flush_cache_all();
++ else
++ flush_data_cache();
+ return;
+ }
+
+- flush_cache_pages(vma, start, end);
++ flush_cache_pages(vma, start & PAGE_MASK, end);
+ }
+
+ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
+ {
+- if (WARN_ON(!pfn_valid(pfn)))
+- return;
+- if (parisc_requires_coherency())
+- flush_user_cache_page(vma, vmaddr);
+- else
+- __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
++ __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
+ }
+
+ void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
+@@ -779,34 +782,133 @@ void flush_anon_page(struct vm_area_stru
+ if (!PageAnon(page))
+ return;
+
+- if (parisc_requires_coherency()) {
+- if (vma->vm_flags & VM_SHARED)
+- flush_data_cache();
+- else
+- flush_user_cache_page(vma, vmaddr);
++ __flush_cache_page(vma, vmaddr, PFN_PHYS(page_to_pfn(page)));
++}
++
++int ptep_clear_flush_young(struct vm_area_struct *vma, unsigned long addr,
++ pte_t *ptep)
++{
++ pte_t pte = ptep_get(ptep);
++
++ if (!pte_young(pte))
++ return 0;
++ set_pte(ptep, pte_mkold(pte));
++#if CONFIG_FLUSH_PAGE_ACCESSED
++ __flush_cache_page(vma, addr, PFN_PHYS(pte_pfn(pte)));
++#endif
++ return 1;
++}
++
++/*
++ * After a PTE is cleared, we have no way to flush the cache for
++ * the physical page. On PA8800 and PA8900 processors, these lines
++ * can cause random cache corruption. Thus, we must flush the cache
++ * as well as the TLB when clearing a PTE that's valid.
++ */
++pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr,
++ pte_t *ptep)
++{
++ struct mm_struct *mm = (vma)->vm_mm;
++ pte_t pte = ptep_get_and_clear(mm, addr, ptep);
++ unsigned long pfn = pte_pfn(pte);
++
++ if (pfn_valid(pfn))
++ __flush_cache_page(vma, addr, PFN_PHYS(pfn));
++ else if (pte_accessible(mm, pte))
++ flush_tlb_page(vma, addr);
++
++ return pte;
++}
++
++/*
++ * The physical address for pages in the ioremap case can be obtained
++ * from the vm_struct struct. I wasn't able to successfully handle the
++ * vmalloc and vmap cases. We have an array of struct page pointers in
++ * the uninitialized vmalloc case but the flush failed using page_to_pfn.
++ */
++void flush_cache_vmap(unsigned long start, unsigned long end)
++{
++ unsigned long addr, physaddr;
++ struct vm_struct *vm;
++
++ /* Prevent cache move-in */
++ flush_tlb_kernel_range(start, end);
++
++ if (end - start >= parisc_cache_flush_threshold) {
++ flush_cache_all();
+ return;
+ }
+
+- flush_tlb_page(vma, vmaddr);
+- preempt_disable();
+- flush_dcache_page_asm(page_to_phys(page), vmaddr);
+- preempt_enable();
++ if (WARN_ON_ONCE(!is_vmalloc_addr((void *)start))) {
++ flush_cache_all();
++ return;
++ }
++
++ vm = find_vm_area((void *)start);
++ if (WARN_ON_ONCE(!vm)) {
++ flush_cache_all();
++ return;
++ }
++
++ /* The physical addresses of IOREMAP regions are contiguous */
++ if (vm->flags & VM_IOREMAP) {
++ physaddr = vm->phys_addr;
++ for (addr = start; addr < end; addr += PAGE_SIZE) {
++ preempt_disable();
++ flush_dcache_page_asm(physaddr, start);
++ flush_icache_page_asm(physaddr, start);
++ preempt_enable();
++ physaddr += PAGE_SIZE;
++ }
++ return;
++ }
++
++ flush_cache_all();
+ }
++EXPORT_SYMBOL(flush_cache_vmap);
+
++/*
++ * The vm_struct has been retired and the page table is set up. The
++ * last page in the range is a guard page. Its physical address can't
++ * be determined using lpa, so there is no way to flush the range
++ * using flush_dcache_page_asm.
++ */
++void flush_cache_vunmap(unsigned long start, unsigned long end)
++{
++ /* Prevent cache move-in */
++ flush_tlb_kernel_range(start, end);
++ flush_data_cache();
++}
++EXPORT_SYMBOL(flush_cache_vunmap);
++
++/*
++ * On systems with PA8800/PA8900 processors, there is no way to flush
++ * a vmap range other than using the architected loop to flush the
++ * entire cache. The page directory is not set up, so we can't use
++ * fdc, etc. FDCE/FICE don't work to flush a portion of the cache.
++ * L2 is physically indexed but FDCE/FICE instructions in virtual
++ * mode output their virtual address on the core bus, not their
++ * real address. As a result, the L2 cache index formed from the
++ * virtual address will most likely not be the same as the L2 index
++ * formed from the real address.
++ */
+ void flush_kernel_vmap_range(void *vaddr, int size)
+ {
+ unsigned long start = (unsigned long)vaddr;
+ unsigned long end = start + size;
+
+- if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+- (unsigned long)size >= parisc_cache_flush_threshold) {
+- flush_tlb_kernel_range(start, end);
+- flush_data_cache();
++ flush_tlb_kernel_range(start, end);
++
++ if (!static_branch_likely(&parisc_has_dcache))
++ return;
++
++ /* If interrupts are disabled, we can only do local flush */
++ if (WARN_ON(IS_ENABLED(CONFIG_SMP) && arch_irqs_disabled())) {
++ flush_data_cache_local(NULL);
+ return;
+ }
+
+- flush_kernel_dcache_range_asm(start, end);
+- flush_tlb_kernel_range(start, end);
++ flush_data_cache();
+ }
+ EXPORT_SYMBOL(flush_kernel_vmap_range);
+
+@@ -818,15 +920,18 @@ void invalidate_kernel_vmap_range(void *
+ /* Ensure DMA is complete */
+ asm_syncdma();
+
+- if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+- (unsigned long)size >= parisc_cache_flush_threshold) {
+- flush_tlb_kernel_range(start, end);
+- flush_data_cache();
++ flush_tlb_kernel_range(start, end);
++
++ if (!static_branch_likely(&parisc_has_dcache))
++ return;
++
++ /* If interrupts are disabled, we can only do local flush */
++ if (WARN_ON(IS_ENABLED(CONFIG_SMP) && arch_irqs_disabled())) {
++ flush_data_cache_local(NULL);
+ return;
+ }
+
+- purge_kernel_dcache_range_asm(start, end);
+- flush_tlb_kernel_range(start, end);
++ flush_data_cache();
+ }
+ EXPORT_SYMBOL(invalidate_kernel_vmap_range);
+
--- /dev/null
+From fe8a08973a0dea9757394c5adbdc3c0a03b0b432 Mon Sep 17 00:00:00 2001
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+Date: Fri, 7 Jun 2024 16:32:59 -0500
+Subject: RAS/AMD/ATL: Fix MI300 bank hash
+
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+
+commit fe8a08973a0dea9757394c5adbdc3c0a03b0b432 upstream.
+
+Apply the SID bits to the correct offset in the Bank value. Do this in
+the temporary value so they don't need to be masked off later.
+
+Fixes: 87a612375307 ("RAS/AMD/ATL: Add MI300 DRAM to normalized address translation support")
+Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Cc: <stable@kernel.org>
+Link: https://lore.kernel.org/r/20240607-mi300-dram-xl-fix-v1-1-2f11547a178c@amd.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ras/amd/atl/umc.c | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/ras/amd/atl/umc.c b/drivers/ras/amd/atl/umc.c
+index 59b6169093f7..5cb92330dc67 100644
+--- a/drivers/ras/amd/atl/umc.c
++++ b/drivers/ras/amd/atl/umc.c
+@@ -189,16 +189,11 @@ static unsigned long convert_dram_to_norm_addr_mi300(unsigned long addr)
+
+ /* Calculate hash for PC bit. */
+ if (addr_hash.pc.xor_enable) {
+- /* Bits SID[1:0] act as Bank[6:5] for PC hash, so apply them here. */
+- bank |= sid << 5;
+-
+ temp = bitwise_xor_bits(col & addr_hash.pc.col_xor);
+ temp ^= bitwise_xor_bits(row & addr_hash.pc.row_xor);
+- temp ^= bitwise_xor_bits(bank & addr_hash.bank_xor);
++ /* Bits SID[1:0] act as Bank[5:4] for PC hash, so apply them here. */
++ temp ^= bitwise_xor_bits((bank | sid << NUM_BANK_BITS) & addr_hash.bank_xor);
+ pc ^= temp;
+-
+- /* Drop SID bits for the sake of debug printing later. */
+- bank &= 0x1F;
+ }
+
+ /* Reconstruct the normalized address starting with NA[4:0] = 0 */
+--
+2.45.2
+
--- /dev/null
+From ba437905b4fbf0ee1686c175069239a1cc292558 Mon Sep 17 00:00:00 2001
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+Date: Fri, 7 Jun 2024 16:33:00 -0500
+Subject: RAS/AMD/ATL: Use system settings for MI300 DRAM to normalized address translation
+
+From: Yazen Ghannam <yazen.ghannam@amd.com>
+
+commit ba437905b4fbf0ee1686c175069239a1cc292558 upstream.
+
+The currently used normalized address format is not applicable to all
+MI300 systems. This leads to incorrect results during address
+translation.
+
+Drop the fixed layout and construct the normalized address from system
+settings.
+
+Fixes: 87a612375307 ("RAS/AMD/ATL: Add MI300 DRAM to normalized address translation support")
+Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Cc: <stable@kernel.org>
+Link: https://lore.kernel.org/r/20240607-mi300-dram-xl-fix-v1-2-2f11547a178c@amd.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ras/amd/atl/internal.h | 2
+ drivers/ras/amd/atl/system.c | 2
+ drivers/ras/amd/atl/umc.c | 157 ++++++++++++++++++++++++++++++-----------
+ 3 files changed, 117 insertions(+), 44 deletions(-)
+
+--- a/drivers/ras/amd/atl/internal.h
++++ b/drivers/ras/amd/atl/internal.h
+@@ -224,7 +224,7 @@ int df_indirect_read_broadcast(u16 node,
+
+ int get_df_system_info(void);
+ int determine_node_id(struct addr_ctx *ctx, u8 socket_num, u8 die_num);
+-int get_addr_hash_mi300(void);
++int get_umc_info_mi300(void);
+
+ int get_address_map(struct addr_ctx *ctx);
+
+--- a/drivers/ras/amd/atl/system.c
++++ b/drivers/ras/amd/atl/system.c
+@@ -127,7 +127,7 @@ static int df4_determine_df_rev(u32 reg)
+ if (reg == DF_FUNC0_ID_MI300) {
+ df_cfg.flags.heterogeneous = 1;
+
+- if (get_addr_hash_mi300())
++ if (get_umc_info_mi300())
+ return -EINVAL;
+ }
+
+--- a/drivers/ras/amd/atl/umc.c
++++ b/drivers/ras/amd/atl/umc.c
+@@ -68,6 +68,8 @@ struct xor_bits {
+ };
+
+ #define NUM_BANK_BITS 4
++#define NUM_COL_BITS 5
++#define NUM_SID_BITS 2
+
+ static struct {
+ /* UMC::CH::AddrHashBank */
+@@ -80,7 +82,22 @@ static struct {
+ u8 bank_xor;
+ } addr_hash;
+
++static struct {
++ u8 bank[NUM_BANK_BITS];
++ u8 col[NUM_COL_BITS];
++ u8 sid[NUM_SID_BITS];
++ u8 num_row_lo;
++ u8 num_row_hi;
++ u8 row_lo;
++ u8 row_hi;
++ u8 pc;
++} bit_shifts;
++
+ #define MI300_UMC_CH_BASE 0x90000
++#define MI300_ADDR_CFG (MI300_UMC_CH_BASE + 0x30)
++#define MI300_ADDR_SEL (MI300_UMC_CH_BASE + 0x40)
++#define MI300_COL_SEL_LO (MI300_UMC_CH_BASE + 0x50)
++#define MI300_ADDR_SEL_2 (MI300_UMC_CH_BASE + 0xA4)
+ #define MI300_ADDR_HASH_BANK0 (MI300_UMC_CH_BASE + 0xC8)
+ #define MI300_ADDR_HASH_PC (MI300_UMC_CH_BASE + 0xE0)
+ #define MI300_ADDR_HASH_PC2 (MI300_UMC_CH_BASE + 0xE4)
+@@ -90,17 +107,42 @@ static struct {
+ #define ADDR_HASH_ROW_XOR GENMASK(31, 14)
+ #define ADDR_HASH_BANK_XOR GENMASK(5, 0)
+
++#define ADDR_CFG_NUM_ROW_LO GENMASK(11, 8)
++#define ADDR_CFG_NUM_ROW_HI GENMASK(15, 12)
++
++#define ADDR_SEL_BANK0 GENMASK(3, 0)
++#define ADDR_SEL_BANK1 GENMASK(7, 4)
++#define ADDR_SEL_BANK2 GENMASK(11, 8)
++#define ADDR_SEL_BANK3 GENMASK(15, 12)
++#define ADDR_SEL_BANK4 GENMASK(20, 16)
++#define ADDR_SEL_ROW_LO GENMASK(27, 24)
++#define ADDR_SEL_ROW_HI GENMASK(31, 28)
++
++#define COL_SEL_LO_COL0 GENMASK(3, 0)
++#define COL_SEL_LO_COL1 GENMASK(7, 4)
++#define COL_SEL_LO_COL2 GENMASK(11, 8)
++#define COL_SEL_LO_COL3 GENMASK(15, 12)
++#define COL_SEL_LO_COL4 GENMASK(19, 16)
++
++#define ADDR_SEL_2_BANK5 GENMASK(4, 0)
++#define ADDR_SEL_2_CHAN GENMASK(15, 12)
++
+ /*
+ * Read UMC::CH::AddrHash{Bank,PC,PC2} registers to get XOR bits used
+- * for hashing. Do this during module init, since the values will not
+- * change during run time.
++ * for hashing.
++ *
++ * Also, read UMC::CH::Addr{Cfg,Sel,Sel2} and UMC::CH:ColSelLo registers to
++ * get the values needed to reconstruct the normalized address. Apply additional
++ * offsets to the raw register values, as needed.
++ *
++ * Do this during module init, since the values will not change during run time.
+ *
+ * These registers are instantiated for each UMC across each AMD Node.
+ * However, they should be identically programmed due to the fixed hardware
+ * design of MI300 systems. So read the values from Node 0 UMC 0 and keep a
+ * single global structure for simplicity.
+ */
+-int get_addr_hash_mi300(void)
++int get_umc_info_mi300(void)
+ {
+ u32 temp;
+ int ret;
+@@ -130,6 +172,44 @@ int get_addr_hash_mi300(void)
+
+ addr_hash.bank_xor = FIELD_GET(ADDR_HASH_BANK_XOR, temp);
+
++ ret = amd_smn_read(0, MI300_ADDR_CFG, &temp);
++ if (ret)
++ return ret;
++
++ bit_shifts.num_row_hi = FIELD_GET(ADDR_CFG_NUM_ROW_HI, temp);
++ bit_shifts.num_row_lo = 10 + FIELD_GET(ADDR_CFG_NUM_ROW_LO, temp);
++
++ ret = amd_smn_read(0, MI300_ADDR_SEL, &temp);
++ if (ret)
++ return ret;
++
++ bit_shifts.bank[0] = 5 + FIELD_GET(ADDR_SEL_BANK0, temp);
++ bit_shifts.bank[1] = 5 + FIELD_GET(ADDR_SEL_BANK1, temp);
++ bit_shifts.bank[2] = 5 + FIELD_GET(ADDR_SEL_BANK2, temp);
++ bit_shifts.bank[3] = 5 + FIELD_GET(ADDR_SEL_BANK3, temp);
++ /* Use BankBit4 for the SID0 position. */
++ bit_shifts.sid[0] = 5 + FIELD_GET(ADDR_SEL_BANK4, temp);
++ bit_shifts.row_lo = 12 + FIELD_GET(ADDR_SEL_ROW_LO, temp);
++ bit_shifts.row_hi = 24 + FIELD_GET(ADDR_SEL_ROW_HI, temp);
++
++ ret = amd_smn_read(0, MI300_COL_SEL_LO, &temp);
++ if (ret)
++ return ret;
++
++ bit_shifts.col[0] = 2 + FIELD_GET(COL_SEL_LO_COL0, temp);
++ bit_shifts.col[1] = 2 + FIELD_GET(COL_SEL_LO_COL1, temp);
++ bit_shifts.col[2] = 2 + FIELD_GET(COL_SEL_LO_COL2, temp);
++ bit_shifts.col[3] = 2 + FIELD_GET(COL_SEL_LO_COL3, temp);
++ bit_shifts.col[4] = 2 + FIELD_GET(COL_SEL_LO_COL4, temp);
++
++ ret = amd_smn_read(0, MI300_ADDR_SEL_2, &temp);
++ if (ret)
++ return ret;
++
++ /* Use BankBit5 for the SID1 position. */
++ bit_shifts.sid[1] = 5 + FIELD_GET(ADDR_SEL_2_BANK5, temp);
++ bit_shifts.pc = 5 + FIELD_GET(ADDR_SEL_2_CHAN, temp);
++
+ return 0;
+ }
+
+@@ -146,9 +226,6 @@ int get_addr_hash_mi300(void)
+ * The MCA address format is as follows:
+ * MCA_ADDR[27:0] = {S[1:0], P[0], R[14:0], B[3:0], C[4:0], Z[0]}
+ *
+- * The normalized address format is fixed in hardware and is as follows:
+- * NA[30:0] = {S[1:0], R[13:0], C4, B[1:0], B[3:2], C[3:2], P, C[1:0], Z[4:0]}
+- *
+ * Additionally, the PC and Bank bits may be hashed. This must be accounted for before
+ * reconstructing the normalized address.
+ */
+@@ -158,18 +235,10 @@ int get_addr_hash_mi300(void)
+ #define MI300_UMC_MCA_PC BIT(25)
+ #define MI300_UMC_MCA_SID GENMASK(27, 26)
+
+-#define MI300_NA_COL_1_0 GENMASK(6, 5)
+-#define MI300_NA_PC BIT(7)
+-#define MI300_NA_COL_3_2 GENMASK(9, 8)
+-#define MI300_NA_BANK_3_2 GENMASK(11, 10)
+-#define MI300_NA_BANK_1_0 GENMASK(13, 12)
+-#define MI300_NA_COL_4 BIT(14)
+-#define MI300_NA_ROW GENMASK(28, 15)
+-#define MI300_NA_SID GENMASK(30, 29)
+-
+ static unsigned long convert_dram_to_norm_addr_mi300(unsigned long addr)
+ {
+- u16 i, col, row, bank, pc, sid, temp;
++ u16 i, col, row, bank, pc, sid;
++ u32 temp;
+
+ col = FIELD_GET(MI300_UMC_MCA_COL, addr);
+ bank = FIELD_GET(MI300_UMC_MCA_BANK, addr);
+@@ -199,34 +268,38 @@ static unsigned long convert_dram_to_nor
+ /* Reconstruct the normalized address starting with NA[4:0] = 0 */
+ addr = 0;
+
+- /* NA[6:5] = Column[1:0] */
+- temp = col & 0x3;
+- addr |= FIELD_PREP(MI300_NA_COL_1_0, temp);
+-
+- /* NA[7] = PC */
+- addr |= FIELD_PREP(MI300_NA_PC, pc);
+-
+- /* NA[9:8] = Column[3:2] */
+- temp = (col >> 2) & 0x3;
+- addr |= FIELD_PREP(MI300_NA_COL_3_2, temp);
+-
+- /* NA[11:10] = Bank[3:2] */
+- temp = (bank >> 2) & 0x3;
+- addr |= FIELD_PREP(MI300_NA_BANK_3_2, temp);
+-
+- /* NA[13:12] = Bank[1:0] */
+- temp = bank & 0x3;
+- addr |= FIELD_PREP(MI300_NA_BANK_1_0, temp);
+-
+- /* NA[14] = Column[4] */
+- temp = (col >> 4) & 0x1;
+- addr |= FIELD_PREP(MI300_NA_COL_4, temp);
++ /* Column bits */
++ for (i = 0; i < NUM_COL_BITS; i++) {
++ temp = (col >> i) & 0x1;
++ addr |= temp << bit_shifts.col[i];
++ }
+
+- /* NA[28:15] = Row[13:0] */
+- addr |= FIELD_PREP(MI300_NA_ROW, row);
++ /* Bank bits */
++ for (i = 0; i < NUM_BANK_BITS; i++) {
++ temp = (bank >> i) & 0x1;
++ addr |= temp << bit_shifts.bank[i];
++ }
++
++ /* Row lo bits */
++ for (i = 0; i < bit_shifts.num_row_lo; i++) {
++ temp = (row >> i) & 0x1;
++ addr |= temp << (i + bit_shifts.row_lo);
++ }
+
+- /* NA[30:29] = SID[1:0] */
+- addr |= FIELD_PREP(MI300_NA_SID, sid);
++ /* Row hi bits */
++ for (i = 0; i < bit_shifts.num_row_hi; i++) {
++ temp = (row >> (i + bit_shifts.num_row_lo)) & 0x1;
++ addr |= temp << (i + bit_shifts.row_hi);
++ }
++
++ /* PC bit */
++ addr |= pc << bit_shifts.pc;
++
++ /* SID bits */
++ for (i = 0; i < NUM_SID_BITS; i++) {
++ temp = (sid >> i) & 0x1;
++ addr |= temp << bit_shifts.sid[i];
++ }
+
+ pr_debug("Addr=0x%016lx", addr);
+ pr_debug("Bank=%u Row=%u Column=%u PC=%u SID=%u", bank, row, col, pc, sid);
bnxt_en-cap-the-size-of-hwrm_port_phy_qcfg-forwarded.patch
af_unix-read-with-msg_peek-loops-if-the-first-unread.patch
bnxt_en-adjust-logging-of-firmware-messages-in-case-.patch
+misc-microchip-pci1xxxx-fix-double-free-in-the-error-handling-of-gp_aux_bus_probe.patch
+ksmbd-move-leading-slash-check-to-smb2_get_name.patch
+ksmbd-fix-missing-use-of-get_write-in-in-smb2_set_ea.patch
+tick-nohz_full-don-t-abuse-smp_call_function_single-in-tick_setup_device.patch
+leds-class-revert-if-no-default-trigger-is-given-make-hw_control-trigger-the-default-trigger.patch
+x86-boot-don-t-add-the-efi-stub-to-targets-again.patch
+iio-adc-ad9467-fix-scan-type-sign.patch
+iio-dac-ad5592r-fix-temperature-channel-scaling-value.patch
+iio-imu-bmi323-fix-trigger-notification-in-case-of-error.patch
+iio-invensense-fix-odr-switching-to-same-value.patch
+iio-pressure-bmp280-fix-bmp580-temperature-reading.patch
+iio-temperature-mlx90635-fix-err_ptr-dereference-in-mlx90635_probe.patch
+iio-imu-inv_icm42600-delete-unneeded-update-watermark-call.patch
+drivers-core-synchronize-really_probe-and-dev_uevent.patch
+parisc-try-to-fix-random-segmentation-faults-in-package-builds.patch
+ras-amd-atl-fix-mi300-bank-hash.patch
+ras-amd-atl-use-system-settings-for-mi300-dram-to-normalized-address-translation.patch
--- /dev/null
+From 07c54cc5988f19c9642fd463c2dbdac7fc52f777 Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Tue, 28 May 2024 14:20:19 +0200
+Subject: tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+commit 07c54cc5988f19c9642fd463c2dbdac7fc52f777 upstream.
+
+After the recent commit 5097cbcb38e6 ("sched/isolation: Prevent boot crash
+when the boot CPU is nohz_full") the kernel no longer crashes, but there is
+another problem.
+
+In this case tick_setup_device() calls tick_take_do_timer_from_boot() to
+update tick_do_timer_cpu and this triggers the WARN_ON_ONCE(irqs_disabled)
+in smp_call_function_single().
+
+Kill tick_take_do_timer_from_boot() and just use WRITE_ONCE(), the new
+comment explains why this is safe (thanks Thomas!).
+
+Fixes: 08ae95f4fd3b ("nohz_full: Allow the boot CPU to be nohz_full")
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240528122019.GA28794@redhat.com
+Link: https://lore.kernel.org/all/20240522151742.GA10400@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/time/tick-common.c | 42 ++++++++++++++----------------------------
+ 1 file changed, 14 insertions(+), 28 deletions(-)
+
+--- a/kernel/time/tick-common.c
++++ b/kernel/time/tick-common.c
+@@ -178,26 +178,6 @@ void tick_setup_periodic(struct clock_ev
+ }
+ }
+
+-#ifdef CONFIG_NO_HZ_FULL
+-static void giveup_do_timer(void *info)
+-{
+- int cpu = *(unsigned int *)info;
+-
+- WARN_ON(tick_do_timer_cpu != smp_processor_id());
+-
+- tick_do_timer_cpu = cpu;
+-}
+-
+-static void tick_take_do_timer_from_boot(void)
+-{
+- int cpu = smp_processor_id();
+- int from = tick_do_timer_boot_cpu;
+-
+- if (from >= 0 && from != cpu)
+- smp_call_function_single(from, giveup_do_timer, &cpu, 1);
+-}
+-#endif
+-
+ /*
+ * Setup the tick device
+ */
+@@ -221,19 +201,25 @@ static void tick_setup_device(struct tic
+ tick_next_period = ktime_get();
+ #ifdef CONFIG_NO_HZ_FULL
+ /*
+- * The boot CPU may be nohz_full, in which case set
+- * tick_do_timer_boot_cpu so the first housekeeping
+- * secondary that comes up will take do_timer from
+- * us.
++ * The boot CPU may be nohz_full, in which case the
++ * first housekeeping secondary will take do_timer()
++ * from it.
+ */
+ if (tick_nohz_full_cpu(cpu))
+ tick_do_timer_boot_cpu = cpu;
+
+- } else if (tick_do_timer_boot_cpu != -1 &&
+- !tick_nohz_full_cpu(cpu)) {
+- tick_take_do_timer_from_boot();
++ } else if (tick_do_timer_boot_cpu != -1 && !tick_nohz_full_cpu(cpu)) {
+ tick_do_timer_boot_cpu = -1;
+- WARN_ON(READ_ONCE(tick_do_timer_cpu) != cpu);
++ /*
++ * The boot CPU will stay in periodic (NOHZ disabled)
++ * mode until clocksource_done_booting() called after
++ * smp_init() selects a high resolution clocksource and
++ * timekeeping_notify() kicks the NOHZ stuff alive.
++ *
++ * So this WRITE_ONCE can only race with the READ_ONCE
++ * check in tick_periodic() but this race is harmless.
++ */
++ WRITE_ONCE(tick_do_timer_cpu, cpu);
+ #endif
+ }
+
--- /dev/null
+From b2747f108b8034271fd5289bd8f3a7003e0775a3 Mon Sep 17 00:00:00 2001
+From: Benjamin Segall <bsegall@google.com>
+Date: Wed, 12 Jun 2024 12:44:44 -0700
+Subject: x86/boot: Don't add the EFI stub to targets, again
+
+From: Benjamin Segall <bsegall@google.com>
+
+commit b2747f108b8034271fd5289bd8f3a7003e0775a3 upstream.
+
+This is a re-commit of
+
+ da05b143a308 ("x86/boot: Don't add the EFI stub to targets")
+
+after the tagged patch incorrectly reverted it.
+
+vmlinux-objs-y is added to targets, with an assumption that they are all
+relative to $(obj); adding a $(objtree)/drivers/... path causes the
+build to incorrectly create a useless
+arch/x86/boot/compressed/drivers/... directory tree.
+
+Fix this just by using a different make variable for the EFI stub.
+
+Fixes: cb8bda8ad443 ("x86/boot/compressed: Rename efi_thunk_64.S to efi-mixed.S")
+Signed-off-by: Ben Segall <bsegall@google.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Cc: stable@vger.kernel.org # v6.1+
+Link: https://lore.kernel.org/r/xm267ceukksz.fsf@bsegall.svl.corp.google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/boot/compressed/Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -116,9 +116,9 @@ vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY)
+
+ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
+ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
+-vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
++vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
+
+-$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
++$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
+ $(call if_changed,ld)
+
+ OBJCOPYFLAGS_vmlinux.bin := -R .comment -S