--- /dev/null
+From 4017ec77dbd0717c41c779c4a5d7952ffc8b2285 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Mar 2025 19:51:29 +0800
+Subject: ASoC: codec: wcd9335: Convert to GPIO descriptors
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit d5099bc1b56417733f4cccf10c61ee74dadd5562 ]
+
+of_gpio.h is deprecated, update the driver to use GPIO descriptors.
+- Use dev_gpiod_get to get GPIO descriptor.
+- Use gpiod_set_value to configure output value.
+
+With legacy of_gpio API, the driver set gpio value 0 to assert reset,
+and 1 to deassert reset. And the reset-gpios use GPIO_ACTIVE_LOW flag in
+DTS, so set GPIOD_OUT_LOW when get GPIO descriptors, and set value 1 means
+output low, set value 0 means output high with gpiod API.
+
+The in-tree DTS files have the right polarity set up already so we can
+expect this to "just work"
+
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Link: https://patch.msgid.link/20250324-wcd-gpiod-v2-3-773f67ce3b56@nxp.com
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd9335.c | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
+index dc4ce2c3f2188..08b7ca26c3c97 100644
+--- a/sound/soc/codecs/wcd9335.c
++++ b/sound/soc/codecs/wcd9335.c
+@@ -16,7 +16,7 @@
+ #include <sound/soc.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc-dapm.h>
+-#include <linux/of_gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/of.h>
+ #include <linux/of_irq.h>
+ #include <sound/tlv.h>
+@@ -338,7 +338,7 @@ struct wcd9335_codec {
+ int comp_enabled[COMPANDER_MAX];
+
+ int intr1;
+- int reset_gpio;
++ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[WCD9335_MAX_SUPPLY];
+
+ unsigned int rx_port_value;
+@@ -5024,12 +5024,11 @@ static const struct regmap_irq_chip wcd9335_regmap_irq1_chip = {
+ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+ {
+ struct device *dev = wcd->dev;
+- struct device_node *np = dev->of_node;
+ int ret;
+
+- wcd->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+- if (wcd->reset_gpio < 0)
+- return dev_err_probe(dev, wcd->reset_gpio, "Reset GPIO missing from DT\n");
++ wcd->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
++ if (IS_ERR(wcd->reset_gpio))
++ return dev_err_probe(dev, PTR_ERR(wcd->reset_gpio), "Reset GPIO missing from DT\n");
+
+ wcd->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(wcd->mclk))
+@@ -5072,9 +5071,9 @@ static int wcd9335_power_on_reset(struct wcd9335_codec *wcd)
+ */
+ usleep_range(600, 650);
+
+- gpio_direction_output(wcd->reset_gpio, 0);
++ gpiod_set_value(wcd->reset_gpio, 1);
+ msleep(20);
+- gpio_set_value(wcd->reset_gpio, 1);
++ gpiod_set_value(wcd->reset_gpio, 0);
+ msleep(20);
+
+ return 0;
+--
+2.39.5
+
--- /dev/null
+From 3752e1c62b4968606391bc8586169eda1b30079f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 May 2025 11:47:01 +0200
+Subject: ASoC: codecs: wcd9335: Fix missing free of regulator supplies
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 9079db287fc3e38e040b0edeb0a25770bb679c8e ]
+
+Driver gets and enables all regulator supplies in probe path
+(wcd9335_parse_dt() and wcd9335_power_on_reset()), but does not cleanup
+in final error paths and in unbind (missing remove() callback). This
+leads to leaked memory and unbalanced regulator enable count during
+probe errors or unbind.
+
+Fix this by converting entire code into devm_regulator_bulk_get_enable()
+which also greatly simplifies the code.
+
+Fixes: 20aedafdf492 ("ASoC: wcd9335: add support to wcd9335 codec")
+Cc: stable@vger.kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20250526-b4-b4-asoc-wcd9395-vdd-px-fixes-v1-1-0b8a2993b7d3@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd9335.c | 25 +++++++------------------
+ 1 file changed, 7 insertions(+), 18 deletions(-)
+
+diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
+index 08b7ca26c3c97..f20d0c9e91e49 100644
+--- a/sound/soc/codecs/wcd9335.c
++++ b/sound/soc/codecs/wcd9335.c
+@@ -339,7 +339,6 @@ struct wcd9335_codec {
+
+ int intr1;
+ struct gpio_desc *reset_gpio;
+- struct regulator_bulk_data supplies[WCD9335_MAX_SUPPLY];
+
+ unsigned int rx_port_value;
+ unsigned int tx_port_value;
+@@ -366,6 +365,10 @@ struct wcd9335_irq {
+ char *name;
+ };
+
++static const char * const wcd9335_supplies[] = {
++ "vdd-buck", "vdd-buck-sido", "vdd-tx", "vdd-rx", "vdd-io",
++};
++
+ static const struct wcd9335_slim_ch wcd9335_tx_chs[WCD9335_TX_MAX] = {
+ WCD9335_SLIM_TX_CH(0),
+ WCD9335_SLIM_TX_CH(1),
+@@ -5038,30 +5041,16 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+ if (IS_ERR(wcd->native_clk))
+ return dev_err_probe(dev, PTR_ERR(wcd->native_clk), "slimbus clock not found\n");
+
+- wcd->supplies[0].supply = "vdd-buck";
+- wcd->supplies[1].supply = "vdd-buck-sido";
+- wcd->supplies[2].supply = "vdd-tx";
+- wcd->supplies[3].supply = "vdd-rx";
+- wcd->supplies[4].supply = "vdd-io";
+-
+- ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, wcd->supplies);
++ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(wcd9335_supplies),
++ wcd9335_supplies);
+ if (ret)
+- return dev_err_probe(dev, ret, "Failed to get supplies\n");
++ return dev_err_probe(dev, ret, "Failed to get and enable supplies\n");
+
+ return 0;
+ }
+
+ static int wcd9335_power_on_reset(struct wcd9335_codec *wcd)
+ {
+- struct device *dev = wcd->dev;
+- int ret;
+-
+- ret = regulator_bulk_enable(WCD9335_MAX_SUPPLY, wcd->supplies);
+- if (ret) {
+- dev_err(dev, "Failed to get supplies: err = %d\n", ret);
+- return ret;
+- }
+-
+ /*
+ * For WCD9335, it takes about 600us for the Vout_A and
+ * Vout_D to be ready after BUCK_SIDO is powered up.
+--
+2.39.5
+
--- /dev/null
+From ab3ce384fb24a3ee3671c39955a6c53d01ce1b87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jun 2024 18:15:17 +0200
+Subject: ASoC: codecs: wcd9335: Handle nicer probe deferral and simplify with
+ dev_err_probe()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 4a03b5dbad466c902d522f3405daa4e5d80578c5 ]
+
+wcd9335_parse_dt() function is called only from probe(), so printing
+errors on resource acquisition is discouraged, because it can pollute
+dmesg. Use dev_err_probe() to fix this and also make the code a bit
+simpler.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://msgid.link/r/20240612-asoc-wcd9xxx-wide-cleanups-v1-4-0d15885b2a06@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wcd9335.c | 28 +++++++++-------------------
+ 1 file changed, 9 insertions(+), 19 deletions(-)
+
+diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
+index 075ed20e9fad8..dc4ce2c3f2188 100644
+--- a/sound/soc/codecs/wcd9335.c
++++ b/sound/soc/codecs/wcd9335.c
+@@ -5028,22 +5028,16 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+ int ret;
+
+ wcd->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+- if (wcd->reset_gpio < 0) {
+- dev_err(dev, "Reset GPIO missing from DT\n");
+- return wcd->reset_gpio;
+- }
++ if (wcd->reset_gpio < 0)
++ return dev_err_probe(dev, wcd->reset_gpio, "Reset GPIO missing from DT\n");
+
+ wcd->mclk = devm_clk_get(dev, "mclk");
+- if (IS_ERR(wcd->mclk)) {
+- dev_err(dev, "mclk not found\n");
+- return PTR_ERR(wcd->mclk);
+- }
++ if (IS_ERR(wcd->mclk))
++ return dev_err_probe(dev, PTR_ERR(wcd->mclk), "mclk not found\n");
+
+ wcd->native_clk = devm_clk_get(dev, "slimbus");
+- if (IS_ERR(wcd->native_clk)) {
+- dev_err(dev, "slimbus clock not found\n");
+- return PTR_ERR(wcd->native_clk);
+- }
++ if (IS_ERR(wcd->native_clk))
++ return dev_err_probe(dev, PTR_ERR(wcd->native_clk), "slimbus clock not found\n");
+
+ wcd->supplies[0].supply = "vdd-buck";
+ wcd->supplies[1].supply = "vdd-buck-sido";
+@@ -5052,10 +5046,8 @@ static int wcd9335_parse_dt(struct wcd9335_codec *wcd)
+ wcd->supplies[4].supply = "vdd-io";
+
+ ret = regulator_bulk_get(dev, WCD9335_MAX_SUPPLY, wcd->supplies);
+- if (ret) {
+- dev_err(dev, "Failed to get supplies: err = %d\n", ret);
+- return ret;
+- }
++ if (ret)
++ return dev_err_probe(dev, ret, "Failed to get supplies\n");
+
+ return 0;
+ }
+@@ -5158,10 +5150,8 @@ static int wcd9335_slim_probe(struct slim_device *slim)
+
+ wcd->dev = dev;
+ ret = wcd9335_parse_dt(wcd);
+- if (ret) {
+- dev_err(dev, "Error parsing DT: %d\n", ret);
++ if (ret)
+ return ret;
+- }
+
+ ret = wcd9335_power_on_reset(wcd);
+ if (ret)
+--
+2.39.5
+
--- /dev/null
+From 2dad055bc504a8e69e11807d6b9bfe4d619de643 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Jun 2025 15:54:05 +0100
+Subject: btrfs: propagate last_unlink_trans earlier when doing a rmdir
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit c466e33e729a0ee017d10d919cba18f503853c60 ]
+
+In case the removed directory had a snapshot that was deleted, we are
+propagating its inode's last_unlink_trans to the parent directory after
+we removed the entry from the parent directory. This leaves a small race
+window where someone can log the parent directory after we removed the
+entry and before we updated last_unlink_trans, and as a result if we ever
+try to replay such a log tree, we will fail since we will attempt to
+remove a snapshot during log replay, which is currently not possible and
+results in the log replay (and mount) to fail. This is the type of failure
+described in commit 1ec9a1ae1e30 ("Btrfs: fix unreplayable log after
+snapshot delete + parent dir fsync").
+
+So fix this by propagating the last_unlink_trans to the parent directory
+before we remove the entry from it.
+
+Fixes: 44f714dae50a ("Btrfs: improve performance on fsync against new inode after rename/unlink")
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 36 ++++++++++++++++++------------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index e3e5bd4fb477a..60079099e24b9 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4655,7 +4655,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
+ struct inode *inode = d_inode(dentry);
+ int err = 0;
+ struct btrfs_trans_handle *trans;
+- u64 last_unlink_trans;
+
+ if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
+ return -ENOTEMPTY;
+@@ -4666,6 +4665,23 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
++ /*
++ * Propagate the last_unlink_trans value of the deleted dir to its
++ * parent directory. This is to prevent an unrecoverable log tree in the
++ * case we do something like this:
++ * 1) create dir foo
++ * 2) create snapshot under dir foo
++ * 3) delete the snapshot
++ * 4) rmdir foo
++ * 5) mkdir foo
++ * 6) fsync foo or some file inside foo
++ *
++ * This is because we can't unlink other roots when replaying the dir
++ * deletes for directory foo.
++ */
++ if (BTRFS_I(inode)->last_unlink_trans >= trans->transid)
++ BTRFS_I(dir)->last_unlink_trans = BTRFS_I(inode)->last_unlink_trans;
++
+ if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
+ err = btrfs_unlink_subvol(trans, dir, dentry);
+ goto out;
+@@ -4675,28 +4691,12 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
+ if (err)
+ goto out;
+
+- last_unlink_trans = BTRFS_I(inode)->last_unlink_trans;
+-
+ /* now the directory is empty */
+ err = btrfs_unlink_inode(trans, BTRFS_I(dir),
+ BTRFS_I(d_inode(dentry)), dentry->d_name.name,
+ dentry->d_name.len);
+- if (!err) {
++ if (!err)
+ btrfs_i_size_write(BTRFS_I(inode), 0);
+- /*
+- * Propagate the last_unlink_trans value of the deleted dir to
+- * its parent directory. This is to prevent an unrecoverable
+- * log tree in the case we do something like this:
+- * 1) create dir foo
+- * 2) create snapshot under dir foo
+- * 3) delete the snapshot
+- * 4) rmdir foo
+- * 5) mkdir foo
+- * 6) fsync foo or some file inside foo
+- */
+- if (last_unlink_trans >= trans->transid)
+- BTRFS_I(dir)->last_unlink_trans = last_unlink_trans;
+- }
+ out:
+ btrfs_end_transaction(trans);
+ btrfs_btree_balance_dirty(BTRFS_I(dir)->root->fs_info);
+--
+2.39.5
+
--- /dev/null
+From 41d54e6f52c6d59ae8fb06d274763d2d8f2ea296 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Jun 2025 16:37:01 +0100
+Subject: btrfs: use btrfs_record_snapshot_destroy() during rmdir
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 157501b0469969fc1ba53add5049575aadd79d80 ]
+
+We are setting the parent directory's last_unlink_trans directly which
+may result in a concurrent task starting to log the directory not see the
+update and therefore can log the directory after we removed a child
+directory which had a snapshot within instead of falling back to a
+transaction commit. Replaying such a log tree would result in a mount
+failure since we can't currently delete snapshots (and subvolumes) during
+log replay. This is the type of failure described in commit 1ec9a1ae1e30
+("Btrfs: fix unreplayable log after snapshot delete + parent dir fsync").
+
+Fix this by using btrfs_record_snapshot_destroy() which updates the
+last_unlink_trans field while holding the inode's log_mutex lock.
+
+Fixes: 44f714dae50a ("Btrfs: improve performance on fsync against new inode after rename/unlink")
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 60079099e24b9..27aaa5064ff7e 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4680,7 +4680,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
+ * deletes for directory foo.
+ */
+ if (BTRFS_I(inode)->last_unlink_trans >= trans->transid)
+- BTRFS_I(dir)->last_unlink_trans = BTRFS_I(inode)->last_unlink_trans;
++ btrfs_record_snapshot_destroy(trans, BTRFS_I(dir));
+
+ if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
+ err = btrfs_unlink_subvol(trans, dir, dentry);
+--
+2.39.5
+
--- /dev/null
+From befad83b0fa5a57dbef28b1933709addc0cf718d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Jun 2025 12:14:54 +0300
+Subject: RDMA/mlx5: Fix vport loopback for MPV device
+
+From: Patrisious Haddad <phaddad@nvidia.com>
+
+[ Upstream commit a9a9e68954f29b1e197663f76289db4879fd51bb ]
+
+Always enable vport loopback for both MPV devices on driver start.
+
+Previously in some cases related to MPV RoCE, packets weren't correctly
+executing loopback check at vport in FW, since it was disabled.
+Due to complexity of identifying such cases for MPV always enable vport
+loopback for both GVMIs when binding the slave to the master port.
+
+Fixes: 0042f9e458a5 ("RDMA/mlx5: Enable vport loopback when user context or QP mandate")
+Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
+Reviewed-by: Mark Bloch <mbloch@nvidia.com>
+Link: https://patch.msgid.link/d4298f5ebb2197459e9e7221c51ecd6a34699847.1750064969.git.leon@kernel.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/mlx5/main.c | 33 +++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
+index 2236c62a19807..e2f3369342c48 100644
+--- a/drivers/infiniband/hw/mlx5/main.c
++++ b/drivers/infiniband/hw/mlx5/main.c
+@@ -1680,6 +1680,33 @@ static void deallocate_uars(struct mlx5_ib_dev *dev,
+ mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]);
+ }
+
++static int mlx5_ib_enable_lb_mp(struct mlx5_core_dev *master,
++ struct mlx5_core_dev *slave)
++{
++ int err;
++
++ err = mlx5_nic_vport_update_local_lb(master, true);
++ if (err)
++ return err;
++
++ err = mlx5_nic_vport_update_local_lb(slave, true);
++ if (err)
++ goto out;
++
++ return 0;
++
++out:
++ mlx5_nic_vport_update_local_lb(master, false);
++ return err;
++}
++
++static void mlx5_ib_disable_lb_mp(struct mlx5_core_dev *master,
++ struct mlx5_core_dev *slave)
++{
++ mlx5_nic_vport_update_local_lb(slave, false);
++ mlx5_nic_vport_update_local_lb(master, false);
++}
++
+ int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp)
+ {
+ int err = 0;
+@@ -3147,6 +3174,8 @@ static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
+
+ lockdep_assert_held(&mlx5_ib_multiport_mutex);
+
++ mlx5_ib_disable_lb_mp(ibdev->mdev, mpi->mdev);
++
+ mlx5_ib_cleanup_cong_debugfs(ibdev, port_num);
+
+ spin_lock(&port->mp.mpi_lock);
+@@ -3231,6 +3260,10 @@ static bool mlx5_ib_bind_slave_port(struct mlx5_ib_dev *ibdev,
+
+ mlx5_ib_init_cong_debugfs(ibdev, port_num);
+
++ err = mlx5_ib_enable_lb_mp(ibdev->mdev, mpi->mdev);
++ if (err)
++ goto unbind;
++
+ return true;
+
+ unbind:
+--
+2.39.5
+
--- /dev/null
+From 64ee9f643e651bf0a2afa5976e4667c6ab2d8c74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Aug 2022 13:10:37 +0300
+Subject: regulator: Add devm helpers for get and enable
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+[ Upstream commit da279e6965b3838e99e5c0ab8f76b87bf86b31a5 ]
+
+A few regulator consumer drivers seem to be just getting a regulator,
+enabling it and registering a devm-action to disable the regulator at
+the driver detach and then forget about it.
+
+We can simplify this a bit by adding a devm-helper for this pattern.
+Add devm_regulator_get_enable() and devm_regulator_get_enable_optional()
+
+Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
+Link: https://lore.kernel.org/r/ed7b8841193bb9749d426f3cb3b199c9460794cd.1660292316.git.mazziesaccount@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/devres.c | 164 +++++++++++++++++++++++++++++
+ include/linux/regulator/consumer.h | 27 +++++
+ 2 files changed, 191 insertions(+)
+
+diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
+index 32823a87fd409..3265e75e97ab4 100644
+--- a/drivers/regulator/devres.c
++++ b/drivers/regulator/devres.c
+@@ -70,6 +70,65 @@ struct regulator *devm_regulator_get_exclusive(struct device *dev,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
+
++static void regulator_action_disable(void *d)
++{
++ struct regulator *r = (struct regulator *)d;
++
++ regulator_disable(r);
++}
++
++static int _devm_regulator_get_enable(struct device *dev, const char *id,
++ int get_type)
++{
++ struct regulator *r;
++ int ret;
++
++ r = _devm_regulator_get(dev, id, get_type);
++ if (IS_ERR(r))
++ return PTR_ERR(r);
++
++ ret = regulator_enable(r);
++ if (!ret)
++ ret = devm_add_action_or_reset(dev, ®ulator_action_disable, r);
++
++ if (ret)
++ devm_regulator_put(r);
++
++ return ret;
++}
++
++/**
++ * devm_regulator_get_enable_optional - Resource managed regulator get and enable
++ * @dev: device to supply
++ * @id: supply name or regulator ID.
++ *
++ * Get and enable regulator for duration of the device life-time.
++ * regulator_disable() and regulator_put() are automatically called on driver
++ * detach. See regulator_get_optional() and regulator_enable() for more
++ * information.
++ */
++int devm_regulator_get_enable_optional(struct device *dev, const char *id)
++{
++ return _devm_regulator_get_enable(dev, id, OPTIONAL_GET);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional);
++
++/**
++ * devm_regulator_get_enable - Resource managed regulator get and enable
++ * @dev: device to supply
++ * @id: supply name or regulator ID.
++ *
++ * Get and enable regulator for duration of the device life-time.
++ * regulator_disable() and regulator_put() are automatically called on driver
++ * detach. See regulator_get() and regulator_enable() for more
++ * information.
++ */
++int devm_regulator_get_enable(struct device *dev, const char *id)
++{
++ return _devm_regulator_get_enable(dev, id, NORMAL_GET);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_get_enable);
++
+ /**
+ * devm_regulator_get_optional - Resource managed regulator_get_optional()
+ * @dev: device to supply
+@@ -194,6 +253,111 @@ int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
+
++static int devm_regulator_bulk_match(struct device *dev, void *res,
++ void *data)
++{
++ struct regulator_bulk_devres *match = res;
++ struct regulator_bulk_data *target = data;
++
++ /*
++ * We check the put uses same consumer list as the get did.
++ * We _could_ scan all entries in consumer array and check the
++ * regulators match but ATM I don't see the need. We can change this
++ * later if needed.
++ */
++ return match->consumers == target;
++}
++
++/**
++ * devm_regulator_bulk_put - Resource managed regulator_bulk_put()
++ * @consumers: consumers to free
++ *
++ * Deallocate regulators allocated with devm_regulator_bulk_get(). Normally
++ * this function will not need to be called and the resource management
++ * code will ensure that the resource is freed.
++ */
++void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
++{
++ int rc;
++ struct regulator *regulator = consumers[0].consumer;
++
++ rc = devres_release(regulator->dev, devm_regulator_bulk_release,
++ devm_regulator_bulk_match, consumers);
++ if (rc != 0)
++ WARN_ON(rc);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_bulk_put);
++
++static void devm_regulator_bulk_disable(void *res)
++{
++ struct regulator_bulk_devres *devres = res;
++ int i;
++
++ for (i = 0; i < devres->num_consumers; i++)
++ regulator_disable(devres->consumers[i].consumer);
++}
++
++/**
++ * devm_regulator_bulk_get_enable - managed get'n enable multiple regulators
++ *
++ * @dev: device to supply
++ * @num_consumers: number of consumers to register
++ * @id: list of supply names or regulator IDs
++ *
++ * @return 0 on success, an errno on failure.
++ *
++ * This helper function allows drivers to get several regulator
++ * consumers in one operation with management, the regulators will
++ * automatically be freed when the device is unbound. If any of the
++ * regulators cannot be acquired then any regulators that were
++ * allocated will be freed before returning to the caller.
++ */
++int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
++ const char * const *id)
++{
++ struct regulator_bulk_devres *devres;
++ struct regulator_bulk_data *consumers;
++ int i, ret;
++
++ devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL);
++ if (!devres)
++ return -ENOMEM;
++
++ devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers),
++ GFP_KERNEL);
++ consumers = devres->consumers;
++ if (!consumers)
++ return -ENOMEM;
++
++ devres->num_consumers = num_consumers;
++
++ for (i = 0; i < num_consumers; i++)
++ consumers[i].supply = id[i];
++
++ ret = devm_regulator_bulk_get(dev, num_consumers, consumers);
++ if (ret)
++ return ret;
++
++ for (i = 0; i < num_consumers; i++) {
++ ret = regulator_enable(consumers[i].consumer);
++ if (ret)
++ goto unwind;
++ }
++
++ ret = devm_add_action(dev, devm_regulator_bulk_disable, devres);
++ if (!ret)
++ return 0;
++
++unwind:
++ while (--i >= 0)
++ regulator_disable(consumers[i].consumer);
++
++ devm_regulator_bulk_put(consumers);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable);
++
+ static void devm_rdev_release(struct device *dev, void *res)
+ {
+ regulator_unregister(*(struct regulator_dev **)res);
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index 61f922e6fe353..a1fce0f27ce16 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -203,6 +203,8 @@ struct regulator *__must_check regulator_get_optional(struct device *dev,
+ const char *id);
+ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
+ const char *id);
++int devm_regulator_get_enable(struct device *dev, const char *id);
++int devm_regulator_get_enable_optional(struct device *dev, const char *id);
+ void regulator_put(struct regulator *regulator);
+ void devm_regulator_put(struct regulator *regulator);
+
+@@ -240,12 +242,15 @@ int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers);
+ int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers);
++void devm_regulator_bulk_put(struct regulator_bulk_data *consumers);
+ int __must_check devm_regulator_bulk_get_const(
+ struct device *dev, int num_consumers,
+ const struct regulator_bulk_data *in_consumers,
+ struct regulator_bulk_data **out_consumers);
+ int __must_check regulator_bulk_enable(int num_consumers,
+ struct regulator_bulk_data *consumers);
++int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers,
++ const char * const *id);
+ int regulator_bulk_disable(int num_consumers,
+ struct regulator_bulk_data *consumers);
+ int regulator_bulk_force_disable(int num_consumers,
+@@ -350,6 +355,17 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
+ return ERR_PTR(-ENODEV);
+ }
+
++static inline int devm_regulator_get_enable(struct device *dev, const char *id)
++{
++ return -ENODEV;
++}
++
++static inline int devm_regulator_get_enable_optional(struct device *dev,
++ const char *id)
++{
++ return -ENODEV;
++}
++
+ static inline struct regulator *__must_check
+ regulator_get_optional(struct device *dev, const char *id)
+ {
+@@ -371,6 +387,10 @@ static inline void devm_regulator_put(struct regulator *regulator)
+ {
+ }
+
++static inline void devm_regulator_bulk_put(struct regulator_bulk_data *consumers)
++{
++}
++
+ static inline int regulator_register_supply_alias(struct device *dev,
+ const char *id,
+ struct device *alias_dev,
+@@ -461,6 +481,13 @@ static inline int regulator_bulk_enable(int num_consumers,
+ return 0;
+ }
+
++static inline int devm_regulator_bulk_get_enable(struct device *dev,
++ int num_consumers,
++ const char * const *id)
++{
++ return 0;
++}
++
+ static inline int regulator_bulk_disable(int num_consumers,
+ struct regulator_bulk_data *consumers)
+ {
+--
+2.39.5
+
--- /dev/null
+From 80620341370aac64b78c5d2739d121bfa0a3c5ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Jul 2022 10:38:23 -0700
+Subject: regulator: core: Allow drivers to define their init data as const
+
+From: Douglas Anderson <dianders@chromium.org>
+
+[ Upstream commit 1de452a0edda26f1483d1d934f692eab13ba669a ]
+
+Drivers tend to want to define the names of their regulators somewhere
+in their source file as "static const". This means, inevitable, that
+every driver out there open codes something like this:
+
+static const char * const supply_names[] = {
+ "vcc", "vccl",
+};
+
+static int get_regulators(struct my_data *data)
+{
+ int i;
+
+ data->supplies = devm_kzalloc(...)
+ if (!data->supplies)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+ data->supplies[i].supply = supply_names[i];
+
+ return devm_regulator_bulk_get(data->dev,
+ ARRAY_SIZE(supply_names),
+ data->supplies);
+}
+
+Let's make this more convenient by doing providing a helper that does
+the copy.
+
+I have chosen to have the "const" input structure here be the exact
+same structure as the normal one passed to
+devm_regulator_bulk_get(). This is slightly inefficent since the input
+data can't possibly have anything useful for "ret" or consumer and
+thus we waste 8 bytes per structure. This seems an OK tradeoff for not
+introducing an extra structure.
+
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://lore.kernel.org/r/20220726103631.v2.6.I38fc508a73135a5c1b873851f3553ff2a3a625f5@changeid
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 9079db287fc3 ("ASoC: codecs: wcd9335: Fix missing free of regulator supplies")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/devres.c | 28 ++++++++++++++++++++++++++++
+ include/linux/regulator/consumer.h | 4 ++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
+index 9113233f41cd1..32823a87fd409 100644
+--- a/drivers/regulator/devres.c
++++ b/drivers/regulator/devres.c
+@@ -166,6 +166,34 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ }
+ EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
+
++/**
++ * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data
++ *
++ * @dev: device to supply
++ * @num_consumers: number of consumers to register
++ * @in_consumers: const configuration of consumers
++ * @out_consumers: in_consumers is copied here and this is passed to
++ * devm_regulator_bulk_get().
++ *
++ * This is a convenience function to allow bulk regulator configuration
++ * to be stored "static const" in files.
++ *
++ * Return: 0 on success, an errno on failure.
++ */
++int devm_regulator_bulk_get_const(struct device *dev, int num_consumers,
++ const struct regulator_bulk_data *in_consumers,
++ struct regulator_bulk_data **out_consumers)
++{
++ *out_consumers = devm_kmemdup(dev, in_consumers,
++ num_consumers * sizeof(*in_consumers),
++ GFP_KERNEL);
++ if (*out_consumers == NULL)
++ return -ENOMEM;
++
++ return devm_regulator_bulk_get(dev, num_consumers, *out_consumers);
++}
++EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const);
++
+ static void devm_rdev_release(struct device *dev, void *res)
+ {
+ regulator_unregister(*(struct regulator_dev **)res);
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index bbf6590a6dec2..61f922e6fe353 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -240,6 +240,10 @@ int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers);
+ int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers);
++int __must_check devm_regulator_bulk_get_const(
++ struct device *dev, int num_consumers,
++ const struct regulator_bulk_data *in_consumers,
++ struct regulator_bulk_data **out_consumers);
+ int __must_check regulator_bulk_enable(int num_consumers,
+ struct regulator_bulk_data *consumers);
+ int regulator_bulk_disable(int num_consumers,
+--
+2.39.5
+
drm-gem-fix-race-in-drm_gem_handle_create_tail.patch
usb-gadget-u_serial-fix-race-condition-in-tty-wakeup.patch
revert-acpi-battery-negate-current-when-discharging.patch
+regulator-core-allow-drivers-to-define-their-init-da.patch
+regulator-add-devm-helpers-for-get-and-enable.patch
+asoc-codecs-wcd9335-handle-nicer-probe-deferral-and-.patch
+asoc-codec-wcd9335-convert-to-gpio-descriptors.patch
+asoc-codecs-wcd9335-fix-missing-free-of-regulator-su.patch
+btrfs-propagate-last_unlink_trans-earlier-when-doing.patch
+btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch
+rdma-mlx5-fix-vport-loopback-for-mpv-device.patch