]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Mon, 24 Aug 2020 01:33:39 +0000 (21:33 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 24 Aug 2020 01:39:28 +0000 (21:39 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
13 files changed:
queue-4.14/asoc-intel-fix-memleak-in-sst_media_open.patch [new file with mode: 0644]
queue-4.14/asoc-msm8916-wcd-analog-fix-register-interrupt-offse.patch [new file with mode: 0644]
queue-4.14/bonding-fix-a-potential-double-unregister.patch [new file with mode: 0644]
queue-4.14/bonding-fix-active-backup-failover-for-current-arp-s.patch [new file with mode: 0644]
queue-4.14/bonding-show-saner-speed-for-broadcast-mode.patch [new file with mode: 0644]
queue-4.14/ext4-fix-potential-negative-array-index-in-do_split.patch [new file with mode: 0644]
queue-4.14/hv_netvsc-fix-the-queue_mapping-in-netvsc_vf_xmit.patch [new file with mode: 0644]
queue-4.14/i40e-fix-crash-during-removing-i40e-driver.patch [new file with mode: 0644]
queue-4.14/i40e-set-rx_only-mode-for-unicast-promiscuous-on-vla.patch [new file with mode: 0644]
queue-4.14/net-dsa-b53-check-for-timeout.patch [new file with mode: 0644]
queue-4.14/net-fec-correct-the-error-path-for-regulator-disable.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/vfio-type1-add-proper-error-unwind-for-vfio_iommu_re.patch [new file with mode: 0644]

diff --git a/queue-4.14/asoc-intel-fix-memleak-in-sst_media_open.patch b/queue-4.14/asoc-intel-fix-memleak-in-sst_media_open.patch
new file mode 100644 (file)
index 0000000..bdefb19
--- /dev/null
@@ -0,0 +1,50 @@
+From d540c5e8bb1d40d1e31b95ba64e5761768f4f7d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Aug 2020 16:41:10 +0800
+Subject: ASoC: intel: Fix memleak in sst_media_open
+
+From: Dinghao Liu <dinghao.liu@zju.edu.cn>
+
+[ Upstream commit 062fa09f44f4fb3776a23184d5d296b0c8872eb9 ]
+
+When power_up_sst() fails, stream needs to be freed
+just like when try_module_get() fails. However, current
+code is returning directly and ends up leaking memory.
+
+Fixes: 0121327c1a68b ("ASoC: Intel: mfld-pcm: add control for powering up/down dsp")
+Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn>
+Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20200813084112.26205-1-dinghao.liu@zju.edu.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/atom/sst-mfld-platform-pcm.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+index 4558c8b930363..3a645fc425cd4 100644
+--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
++++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+@@ -339,7 +339,7 @@ static int sst_media_open(struct snd_pcm_substream *substream,
+       ret_val = power_up_sst(stream);
+       if (ret_val < 0)
+-              return ret_val;
++              goto out_power_up;
+       /* Make sure, that the period size is always even */
+       snd_pcm_hw_constraint_step(substream->runtime, 0,
+@@ -348,8 +348,9 @@ static int sst_media_open(struct snd_pcm_substream *substream,
+       return snd_pcm_hw_constraint_integer(runtime,
+                        SNDRV_PCM_HW_PARAM_PERIODS);
+ out_ops:
+-      kfree(stream);
+       mutex_unlock(&sst_lock);
++out_power_up:
++      kfree(stream);
+       return ret_val;
+ }
+-- 
+2.25.1
+
diff --git a/queue-4.14/asoc-msm8916-wcd-analog-fix-register-interrupt-offse.patch b/queue-4.14/asoc-msm8916-wcd-analog-fix-register-interrupt-offse.patch
new file mode 100644 (file)
index 0000000..1b9ce82
--- /dev/null
@@ -0,0 +1,42 @@
+From 9cee5c6f098b7211741ed0424328ec4031817418 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Aug 2020 11:34:52 +0100
+Subject: ASoC: msm8916-wcd-analog: fix register Interrupt offset
+
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+[ Upstream commit ff69c97ef84c9f7795adb49e9f07c9adcdd0c288 ]
+
+For some reason interrupt set and clear register offsets are
+not set correctly.
+This patch corrects them!
+
+Fixes: 585e881e5b9e ("ASoC: codecs: Add msm8916-wcd analog codec")
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Tested-by: Stephan Gerhold <stephan@gerhold.net>
+Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
+Link: https://lore.kernel.org/r/20200811103452.20448-1-srinivas.kandagatla@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/msm8916-wcd-analog.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c
+index 3633eb30dd135..4f949ad50d6a7 100644
+--- a/sound/soc/codecs/msm8916-wcd-analog.c
++++ b/sound/soc/codecs/msm8916-wcd-analog.c
+@@ -16,8 +16,8 @@
+ #define CDC_D_REVISION1                       (0xf000)
+ #define CDC_D_PERPH_SUBTYPE           (0xf005)
+-#define CDC_D_INT_EN_SET              (0x015)
+-#define CDC_D_INT_EN_CLR              (0x016)
++#define CDC_D_INT_EN_SET              (0xf015)
++#define CDC_D_INT_EN_CLR              (0xf016)
+ #define MBHC_SWITCH_INT                       BIT(7)
+ #define MBHC_MIC_ELECTRICAL_INS_REM_DET       BIT(6)
+ #define MBHC_BUTTON_PRESS_DET         BIT(5)
+-- 
+2.25.1
+
diff --git a/queue-4.14/bonding-fix-a-potential-double-unregister.patch b/queue-4.14/bonding-fix-a-potential-double-unregister.patch
new file mode 100644 (file)
index 0000000..bc26d36
--- /dev/null
@@ -0,0 +1,48 @@
+From 990abe5ab96f4414afc7429da88933497163bf8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Aug 2020 20:05:58 -0700
+Subject: bonding: fix a potential double-unregister
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+[ Upstream commit 832707021666411d04795c564a4adea5d6b94f17 ]
+
+When we tear down a network namespace, we unregister all
+the netdevices within it. So we may queue a slave device
+and a bonding device together in the same unregister queue.
+
+If the only slave device is non-ethernet, it would
+automatically unregister the bonding device as well. Thus,
+we may end up unregistering the bonding device twice.
+
+Workaround this special case by checking reg_state.
+
+Fixes: 9b5e383c11b0 ("net: Introduce unregister_netdevice_many()")
+Reported-by: syzbot+af23e7f3e0a7e10c8b67@syzkaller.appspotmail.com
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Cc: Andy Gospodarek <andy@greyhouse.net>
+Cc: Jay Vosburgh <j.vosburgh@gmail.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 9ddbafdca3b05..a6d8d3b3c903d 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -2010,7 +2010,8 @@ static int  bond_release_and_destroy(struct net_device *bond_dev,
+       int ret;
+       ret = __bond_release_one(bond_dev, slave_dev, false, true);
+-      if (ret == 0 && !bond_has_slaves(bond)) {
++      if (ret == 0 && !bond_has_slaves(bond) &&
++          bond_dev->reg_state != NETREG_UNREGISTERING) {
+               bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
+               netdev_info(bond_dev, "Destroying bond %s\n",
+                           bond_dev->name);
+-- 
+2.25.1
+
diff --git a/queue-4.14/bonding-fix-active-backup-failover-for-current-arp-s.patch b/queue-4.14/bonding-fix-active-backup-failover-for-current-arp-s.patch
new file mode 100644 (file)
index 0000000..8c3ba68
--- /dev/null
@@ -0,0 +1,90 @@
+From 846586679f51bba70846ebfb4157b208ed895ffc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Aug 2020 20:52:44 +0200
+Subject: bonding: fix active-backup failover for current ARP slave
+
+From: Jiri Wiesner <jwiesner@suse.com>
+
+[ Upstream commit 0410d07190961ac526f05085765a8d04d926545b ]
+
+When the ARP monitor is used for link detection, ARP replies are
+validated for all slaves (arp_validate=3) and fail_over_mac is set to
+active, two slaves of an active-backup bond may get stuck in a state
+where both of them are active and pass packets that they receive to
+the bond. This state makes IPv6 duplicate address detection fail. The
+state is reached thus:
+1. The current active slave goes down because the ARP target
+   is not reachable.
+2. The current ARP slave is chosen and made active.
+3. A new slave is enslaved. This new slave becomes the current active
+   slave and can reach the ARP target.
+As a result, the current ARP slave stays active after the enslave
+action has finished and the log is littered with "PROBE BAD" messages:
+> bond0: PROBE: c_arp ens10 && cas ens11 BAD
+The workaround is to remove the slave with "going back" status from
+the bond and re-enslave it. This issue was encountered when DPDK PMD
+interfaces were being enslaved to an active-backup bond.
+
+I would be possible to fix the issue in bond_enslave() or
+bond_change_active_slave() but the ARP monitor was fixed instead to
+keep most of the actions changing the current ARP slave in the ARP
+monitor code. The current ARP slave is set as inactive and backup
+during the commit phase. A new state, BOND_LINK_FAIL, has been
+introduced for slaves in the context of the ARP monitor. This allows
+administrators to see how slaves are rotated for sending ARP requests
+and attempts are made to find a new active slave.
+
+Fixes: b2220cad583c9 ("bonding: refactor ARP active-backup monitor")
+Signed-off-by: Jiri Wiesner <jwiesner@suse.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index a6d8d3b3c903d..861d2c0a521a4 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -2753,6 +2753,9 @@ static int bond_ab_arp_inspect(struct bonding *bond)
+                       if (bond_time_in_interval(bond, last_rx, 1)) {
+                               bond_propose_link_state(slave, BOND_LINK_UP);
+                               commit++;
++                      } else if (slave->link == BOND_LINK_BACK) {
++                              bond_propose_link_state(slave, BOND_LINK_FAIL);
++                              commit++;
+                       }
+                       continue;
+               }
+@@ -2863,6 +2866,19 @@ static void bond_ab_arp_commit(struct bonding *bond)
+                       continue;
++              case BOND_LINK_FAIL:
++                      bond_set_slave_link_state(slave, BOND_LINK_FAIL,
++                                                BOND_SLAVE_NOTIFY_NOW);
++                      bond_set_slave_inactive_flags(slave,
++                                                    BOND_SLAVE_NOTIFY_NOW);
++
++                      /* A slave has just been enslaved and has become
++                       * the current active slave.
++                       */
++                      if (rtnl_dereference(bond->curr_active_slave))
++                              RCU_INIT_POINTER(bond->current_arp_slave, NULL);
++                      continue;
++
+               default:
+                       netdev_err(bond->dev, "impossible: new_link %d on slave %s\n",
+                                  slave->link_new_state, slave->dev->name);
+@@ -2912,8 +2928,6 @@ static bool bond_ab_arp_probe(struct bonding *bond)
+                       return should_notify_rtnl;
+       }
+-      bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER);
+-
+       bond_for_each_slave_rcu(bond, slave, iter) {
+               if (!found && !before && bond_slave_is_up(slave))
+                       before = slave;
+-- 
+2.25.1
+
diff --git a/queue-4.14/bonding-show-saner-speed-for-broadcast-mode.patch b/queue-4.14/bonding-show-saner-speed-for-broadcast-mode.patch
new file mode 100644 (file)
index 0000000..0d0f7c6
--- /dev/null
@@ -0,0 +1,79 @@
+From e234bfc93c930627078c7349c1613ee6628f6ca3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Aug 2020 10:09:00 -0400
+Subject: bonding: show saner speed for broadcast mode
+
+From: Jarod Wilson <jarod@redhat.com>
+
+[ Upstream commit 4ca0d9ac3fd8f9f90b72a15d8da2aca3ffb58418 ]
+
+Broadcast mode bonds transmit a copy of all traffic simultaneously out of
+all interfaces, so the "speed" of the bond isn't really the aggregate of
+all interfaces, but rather, the speed of the slowest active interface.
+
+Also, the type of the speed field is u32, not unsigned long, so adjust
+that accordingly, as required to make min() function here without
+complaining about mismatching types.
+
+Fixes: bb5b052f751b ("bond: add support to read speed and duplex via ethtool")
+CC: Jay Vosburgh <j.vosburgh@gmail.com>
+CC: Veaceslav Falico <vfalico@gmail.com>
+CC: Andy Gospodarek <andy@greyhouse.net>
+CC: "David S. Miller" <davem@davemloft.net>
+CC: netdev@vger.kernel.org
+Acked-by: Jay Vosburgh <jay.vosburgh@canonical.com>
+Signed-off-by: Jarod Wilson <jarod@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 1f867e275408e..9ddbafdca3b05 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -4156,13 +4156,23 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
+       return ret;
+ }
++static u32 bond_mode_bcast_speed(struct slave *slave, u32 speed)
++{
++      if (speed == 0 || speed == SPEED_UNKNOWN)
++              speed = slave->speed;
++      else
++              speed = min(speed, slave->speed);
++
++      return speed;
++}
++
+ static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
+                                          struct ethtool_link_ksettings *cmd)
+ {
+       struct bonding *bond = netdev_priv(bond_dev);
+-      unsigned long speed = 0;
+       struct list_head *iter;
+       struct slave *slave;
++      u32 speed = 0;
+       cmd->base.duplex = DUPLEX_UNKNOWN;
+       cmd->base.port = PORT_OTHER;
+@@ -4174,8 +4184,13 @@ static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
+        */
+       bond_for_each_slave(bond, slave, iter) {
+               if (bond_slave_can_tx(slave)) {
+-                      if (slave->speed != SPEED_UNKNOWN)
+-                              speed += slave->speed;
++                      if (slave->speed != SPEED_UNKNOWN) {
++                              if (BOND_MODE(bond) == BOND_MODE_BROADCAST)
++                                      speed = bond_mode_bcast_speed(slave,
++                                                                    speed);
++                              else
++                                      speed += slave->speed;
++                      }
+                       if (cmd->base.duplex == DUPLEX_UNKNOWN &&
+                           slave->duplex != DUPLEX_UNKNOWN)
+                               cmd->base.duplex = slave->duplex;
+-- 
+2.25.1
+
diff --git a/queue-4.14/ext4-fix-potential-negative-array-index-in-do_split.patch b/queue-4.14/ext4-fix-potential-negative-array-index-in-do_split.patch
new file mode 100644 (file)
index 0000000..1bdb48d
--- /dev/null
@@ -0,0 +1,68 @@
+From a1caec6a6cfffb47e921fcb7b4aa520a5523b339 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jun 2020 14:19:04 -0500
+Subject: ext4: fix potential negative array index in do_split()
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+[ Upstream commit 5872331b3d91820e14716632ebb56b1399b34fe1 ]
+
+If for any reason a directory passed to do_split() does not have enough
+active entries to exceed half the size of the block, we can end up
+iterating over all "count" entries without finding a split point.
+
+In this case, count == move, and split will be zero, and we will
+attempt a negative index into map[].
+
+Guard against this by detecting this case, and falling back to
+split-to-half-of-count instead; in this case we will still have
+plenty of space (> half blocksize) in each split block.
+
+Fixes: ef2b02d3e617 ("ext34: ensure do_split leaves enough free space in both blocks")
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/f53e246b-647c-64bb-16ec-135383c70ad7@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/namei.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index ed17edb31e22f..3f999053457b6 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1741,7 +1741,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+                            blocksize, hinfo, map);
+       map -= count;
+       dx_sort_map(map, count);
+-      /* Split the existing block in the middle, size-wise */
++      /* Ensure that neither split block is over half full */
+       size = 0;
+       move = 0;
+       for (i = count-1; i >= 0; i--) {
+@@ -1751,8 +1751,18 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
+               size += map[i].size;
+               move++;
+       }
+-      /* map index at which we will split */
+-      split = count - move;
++      /*
++       * map index at which we will split
++       *
++       * If the sum of active entries didn't exceed half the block size, just
++       * split it in half by count; each resulting block will have at least
++       * half the space free.
++       */
++      if (i > 0)
++              split = count - move;
++      else
++              split = count/2;
++
+       hash2 = map[split].hash;
+       continued = hash2 == map[split - 1].hash;
+       dxtrace(printk(KERN_INFO "Split block %lu at %x, %i/%i\n",
+-- 
+2.25.1
+
diff --git a/queue-4.14/hv_netvsc-fix-the-queue_mapping-in-netvsc_vf_xmit.patch b/queue-4.14/hv_netvsc-fix-the-queue_mapping-in-netvsc_vf_xmit.patch
new file mode 100644 (file)
index 0000000..d59ae21
--- /dev/null
@@ -0,0 +1,45 @@
+From ff66d87c06f36d2f08a5079b05b257a7aa12efee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Aug 2020 14:53:15 -0700
+Subject: hv_netvsc: Fix the queue_mapping in netvsc_vf_xmit()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Haiyang Zhang <haiyangz@microsoft.com>
+
+[ Upstream commit c3d897e01aef8ddc43149e4d661b86f823e3aae7 ]
+
+netvsc_vf_xmit() / dev_queue_xmit() will call VF NIC’s ndo_select_queue
+or netdev_pick_tx() again. They will use skb_get_rx_queue() to get the
+queue number, so the “skb->queue_mapping - 1” will be used. This may
+cause the last queue of VF not been used.
+
+Use skb_record_rx_queue() here, so that the skb_get_rx_queue() called
+later will get the correct queue number, and VF will be able to use
+all queues.
+
+Fixes: b3bf5666a510 ("hv_netvsc: defer queue selection to VF")
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/hyperv/netvsc_drv.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index 10c3480c2da89..dbc6c9ed1c8f8 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -500,7 +500,7 @@ static int netvsc_vf_xmit(struct net_device *net, struct net_device *vf_netdev,
+       int rc;
+       skb->dev = vf_netdev;
+-      skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
++      skb_record_rx_queue(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping);
+       rc = dev_queue_xmit(skb);
+       if (likely(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN)) {
+-- 
+2.25.1
+
diff --git a/queue-4.14/i40e-fix-crash-during-removing-i40e-driver.patch b/queue-4.14/i40e-fix-crash-during-removing-i40e-driver.patch
new file mode 100644 (file)
index 0000000..31bc4b7
--- /dev/null
@@ -0,0 +1,80 @@
+From a1186f74f2537665047c800b4e28d9fe0b627d4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Aug 2020 10:56:49 +0000
+Subject: i40e: Fix crash during removing i40e driver
+
+From: Grzegorz Szczurek <grzegorzx.szczurek@intel.com>
+
+[ Upstream commit 5b6d4a7f20b09c47ca598760f6dafd554af8b6d5 ]
+
+Fix the reason of crashing system by add waiting time to finish reset
+recovery process before starting remove driver procedure.
+Now VSI is releasing if VSI is not in reset recovery mode.
+Without this fix it was possible to start remove driver if other
+processing command need reset recovery procedure which resulted in
+null pointer dereference. VSI used by the ethtool process has been
+cleared by remove driver process.
+
+[ 6731.508665] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[ 6731.508668] #PF: supervisor read access in kernel mode
+[ 6731.508670] #PF: error_code(0x0000) - not-present page
+[ 6731.508671] PGD 0 P4D 0
+[ 6731.508674] Oops: 0000 [#1] SMP PTI
+[ 6731.508679] Hardware name: Intel Corporation S2600WT2R/S2600WT2R, BIOS SE5C610.86B.01.01.0021.032120170601 03/21/2017
+[ 6731.508694] RIP: 0010:i40e_down+0x252/0x310 [i40e]
+[ 6731.508696] Code: c7 78 de fa c0 e8 61 02 3a c1 66 83 bb f6 0c 00 00 00 0f 84 bf 00 00 00 45 31 e4 45 31 ff eb 03 41 89 c7 48 8b 83 98 0c 00 00 <4a> 8b 3c 20 e8 a5 79 02 00 48 83 bb d0 0c 00 00 00 74 10 48 8b 83
+[ 6731.508698] RSP: 0018:ffffb75ac7b3faf0 EFLAGS: 00010246
+[ 6731.508700] RAX: 0000000000000000 RBX: ffff9c9874bd5000 RCX: 0000000000000007
+[ 6731.508701] RDX: 0000000000000000 RSI: 0000000000000096 RDI: ffff9c987f4d9780
+[ 6731.508703] RBP: ffffb75ac7b3fb30 R08: 0000000000005b60 R09: 0000000000000004
+[ 6731.508704] R10: ffffb75ac64fbd90 R11: 0000000000000001 R12: 0000000000000000
+[ 6731.508706] R13: ffff9c97a08e0000 R14: ffff9c97a08e0a68 R15: 0000000000000000
+[ 6731.508708] FS:  00007f2617cd2740(0000) GS:ffff9c987f4c0000(0000) knlGS:0000000000000000
+[ 6731.508710] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 6731.508711] CR2: 0000000000000000 CR3: 0000001e765c4006 CR4: 00000000003606e0
+[ 6731.508713] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 6731.508714] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 6731.508715] Call Trace:
+[ 6731.508734]  i40e_vsi_close+0x84/0x90 [i40e]
+[ 6731.508742]  i40e_quiesce_vsi.part.98+0x3c/0x40 [i40e]
+[ 6731.508749]  i40e_pf_quiesce_all_vsi+0x55/0x60 [i40e]
+[ 6731.508757]  i40e_prep_for_reset+0x59/0x130 [i40e]
+[ 6731.508765]  i40e_reconfig_rss_queues+0x5a/0x120 [i40e]
+[ 6731.508774]  i40e_set_channels+0xda/0x170 [i40e]
+[ 6731.508778]  ethtool_set_channels+0xe9/0x150
+[ 6731.508781]  dev_ethtool+0x1b94/0x2920
+[ 6731.508805]  dev_ioctl+0xc2/0x590
+[ 6731.508811]  sock_do_ioctl+0xae/0x150
+[ 6731.508813]  sock_ioctl+0x34f/0x3c0
+[ 6731.508821]  ksys_ioctl+0x98/0xb0
+[ 6731.508828]  __x64_sys_ioctl+0x1a/0x20
+[ 6731.508831]  do_syscall_64+0x57/0x1c0
+[ 6731.508835]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+Fixes: 4b8164467b85 ("i40e: Add common function for finding VSI by type")
+Signed-off-by: Grzegorz Szczurek <grzegorzx.szczurek@intel.com>
+Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Tested-by: Aaron Brown <aaron.f.brown@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index aa2b446d6ad0f..f4475cbf8ce86 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -11822,6 +11822,9 @@ static void i40e_remove(struct pci_dev *pdev)
+       i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0);
+       i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0);
++      while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
++              usleep_range(1000, 2000);
++
+       /* no more scheduling of any task */
+       set_bit(__I40E_SUSPENDED, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
+-- 
+2.25.1
+
diff --git a/queue-4.14/i40e-set-rx_only-mode-for-unicast-promiscuous-on-vla.patch b/queue-4.14/i40e-set-rx_only-mode-for-unicast-promiscuous-on-vla.patch
new file mode 100644 (file)
index 0000000..2e4be42
--- /dev/null
@@ -0,0 +1,114 @@
+From 1e836ac5fc02a239526e296f23bc21f90a0bc21d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Aug 2020 13:40:59 +0000
+Subject: i40e: Set RX_ONLY mode for unicast promiscuous on VLAN
+
+From: Przemyslaw Patynowski <przemyslawx.patynowski@intel.com>
+
+[ Upstream commit 4bd5e02a2ed1575c2f65bd3c557a077dd399f0e8 ]
+
+Trusted VF with unicast promiscuous mode set, could listen to TX
+traffic of other VFs.
+Set unicast promiscuous mode to RX traffic, if VSI has port VLAN
+configured. Rename misleading I40E_AQC_SET_VSI_PROMISC_TX bit to
+I40E_AQC_SET_VSI_PROMISC_RX_ONLY. Aligned unicast promiscuous with
+VLAN to the one without VLAN.
+
+Fixes: 6c41a7606967 ("i40e: Add promiscuous on VLAN support")
+Fixes: 3b1200891b7f ("i40e: When in promisc mode apply promisc mode to Tx Traffic as well")
+Signed-off-by: Przemyslaw Patynowski <przemyslawx.patynowski@intel.com>
+Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/intel/i40e/i40e_adminq_cmd.h |  2 +-
+ drivers/net/ethernet/intel/i40e/i40e_common.c | 35 ++++++++++++++-----
+ 2 files changed, 28 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+index 5d5f422cbae55..f82da2b47d9a5 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+@@ -1175,7 +1175,7 @@ struct i40e_aqc_set_vsi_promiscuous_modes {
+ #define I40E_AQC_SET_VSI_PROMISC_BROADCAST    0x04
+ #define I40E_AQC_SET_VSI_DEFAULT              0x08
+ #define I40E_AQC_SET_VSI_PROMISC_VLAN         0x10
+-#define I40E_AQC_SET_VSI_PROMISC_TX           0x8000
++#define I40E_AQC_SET_VSI_PROMISC_RX_ONLY      0x8000
+       __le16  seid;
+ #define I40E_AQC_VSI_PROM_CMD_SEID_MASK               0x3FF
+       __le16  vlan_tag;
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
+index 111426ba5fbce..3fd2dfaf2bd53 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
+@@ -1914,6 +1914,21 @@ i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
+       return status;
+ }
++/**
++ * i40e_is_aq_api_ver_ge
++ * @aq: pointer to AdminQ info containing HW API version to compare
++ * @maj: API major value
++ * @min: API minor value
++ *
++ * Assert whether current HW API version is greater/equal than provided.
++ **/
++static bool i40e_is_aq_api_ver_ge(struct i40e_adminq_info *aq, u16 maj,
++                                u16 min)
++{
++      return (aq->api_maj_ver > maj ||
++              (aq->api_maj_ver == maj && aq->api_min_ver >= min));
++}
++
+ /**
+  * i40e_aq_add_vsi
+  * @hw: pointer to the hw struct
+@@ -2039,18 +2054,16 @@ i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
+       if (set) {
+               flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
+-              if (rx_only_promisc &&
+-                  (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) ||
+-                   (hw->aq.api_maj_ver > 1)))
+-                      flags |= I40E_AQC_SET_VSI_PROMISC_TX;
++              if (rx_only_promisc && i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
++                      flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
+       }
+       cmd->promiscuous_flags = cpu_to_le16(flags);
+       cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
+-      if (((hw->aq.api_maj_ver >= 1) && (hw->aq.api_min_ver >= 5)) ||
+-          (hw->aq.api_maj_ver > 1))
+-              cmd->valid_flags |= cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_TX);
++      if (i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
++              cmd->valid_flags |=
++                      cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
+       cmd->seid = cpu_to_le16(seid);
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+@@ -2147,11 +2160,17 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_set_vsi_promiscuous_modes);
+-      if (enable)
++      if (enable) {
+               flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
++              if (i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
++                      flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
++      }
+       cmd->promiscuous_flags = cpu_to_le16(flags);
+       cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
++      if (i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
++              cmd->valid_flags |=
++                      cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
+       cmd->seid = cpu_to_le16(seid);
+       cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
+-- 
+2.25.1
+
diff --git a/queue-4.14/net-dsa-b53-check-for-timeout.patch b/queue-4.14/net-dsa-b53-check-for-timeout.patch
new file mode 100644 (file)
index 0000000..8b20a36
--- /dev/null
@@ -0,0 +1,51 @@
+From 750dd220603bb0fc5ace4dd053370a57601ef19f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Aug 2020 06:56:00 -0700
+Subject: net: dsa: b53: check for timeout
+
+From: Tom Rix <trix@redhat.com>
+
+[ Upstream commit 774d977abfd024e6f73484544b9abe5a5cd62de7 ]
+
+clang static analysis reports this problem
+
+b53_common.c:1583:13: warning: The left expression of the compound
+  assignment is an uninitialized value. The computed value will
+  also be garbage
+        ent.port &= ~BIT(port);
+        ~~~~~~~~ ^
+
+ent is set by a successful call to b53_arl_read().  Unsuccessful
+calls are caught by an switch statement handling specific returns.
+b32_arl_read() calls b53_arl_op_wait() which fails with the
+unhandled -ETIMEDOUT.
+
+So add -ETIMEDOUT to the switch statement.  Because
+b53_arl_op_wait() already prints out a message, do not add another
+one.
+
+Fixes: 1da6df85c6fb ("net: dsa: b53: Implement ARL add/del/dump operations")
+Signed-off-by: Tom Rix <trix@redhat.com>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
+index 274d369151107..5c3fa0be8844e 100644
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -1160,6 +1160,8 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,
+               return ret;
+       switch (ret) {
++      case -ETIMEDOUT:
++              return ret;
+       case -ENOSPC:
+               dev_dbg(dev->dev, "{%pM,%.4d} no space left in ARL\n",
+                       addr, vid);
+-- 
+2.25.1
+
diff --git a/queue-4.14/net-fec-correct-the-error-path-for-regulator-disable.patch b/queue-4.14/net-fec-correct-the-error-path-for-regulator-disable.patch
new file mode 100644 (file)
index 0000000..1497f79
--- /dev/null
@@ -0,0 +1,40 @@
+From 0281ce18fd22b502035fd50e3674529095a3f212 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Aug 2020 15:13:14 +0800
+Subject: net: fec: correct the error path for regulator disable in probe
+
+From: Fugang Duan <fugang.duan@nxp.com>
+
+[ Upstream commit c6165cf0dbb82ded90163dce3ac183fc7a913dc4 ]
+
+Correct the error path for regulator disable.
+
+Fixes: 9269e5560b26 ("net: fec: add phy-reset-gpios PROBE_DEFER check")
+Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 8ba915cc4c2e4..22f964ef859e5 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -3536,11 +3536,11 @@ fec_probe(struct platform_device *pdev)
+ failed_irq:
+ failed_init:
+       fec_ptp_stop(pdev);
+-      if (fep->reg_phy)
+-              regulator_disable(fep->reg_phy);
+ failed_reset:
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
++      if (fep->reg_phy)
++              regulator_disable(fep->reg_phy);
+ failed_regulator:
+       clk_disable_unprepare(fep->clk_ahb);
+ failed_clk_ahb:
+-- 
+2.25.1
+
index fd9ff4077ad119440ab2d08cf3b0ef919b2995b2..5552461fd452e256074bb96bf1a0cd7d8e210111 100644 (file)
@@ -31,3 +31,15 @@ scsi-libfc-free-skb-in-fc_disc_gpn_id_resp-for-valid.patch
 virtio_ring-avoid-loop-when-vq-is-broken-in-virtqueu.patch
 xfs-fix-ubsan-null-ptr-deref-in-xfs_sysfs_init.patch
 alpha-fix-annotation-of-io-read-write-16-32-be.patch
+ext4-fix-potential-negative-array-index-in-do_split.patch
+i40e-set-rx_only-mode-for-unicast-promiscuous-on-vla.patch
+i40e-fix-crash-during-removing-i40e-driver.patch
+net-fec-correct-the-error-path-for-regulator-disable.patch
+bonding-show-saner-speed-for-broadcast-mode.patch
+bonding-fix-a-potential-double-unregister.patch
+asoc-msm8916-wcd-analog-fix-register-interrupt-offse.patch
+asoc-intel-fix-memleak-in-sst_media_open.patch
+vfio-type1-add-proper-error-unwind-for-vfio_iommu_re.patch
+bonding-fix-active-backup-failover-for-current-arp-s.patch
+hv_netvsc-fix-the-queue_mapping-in-netvsc_vf_xmit.patch
+net-dsa-b53-check-for-timeout.patch
diff --git a/queue-4.14/vfio-type1-add-proper-error-unwind-for-vfio_iommu_re.patch b/queue-4.14/vfio-type1-add-proper-error-unwind-for-vfio_iommu_re.patch
new file mode 100644 (file)
index 0000000..240c8bf
--- /dev/null
@@ -0,0 +1,164 @@
+From f045b3c88e64a741fd65a6ee507620d3c6f427ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Aug 2020 11:09:13 -0600
+Subject: vfio/type1: Add proper error unwind for vfio_iommu_replay()
+
+From: Alex Williamson <alex.williamson@redhat.com>
+
+[ Upstream commit aae7a75a821a793ed6b8ad502a5890fb8e8f172d ]
+
+The vfio_iommu_replay() function does not currently unwind on error,
+yet it does pin pages, perform IOMMU mapping, and modify the vfio_dma
+structure to indicate IOMMU mapping.  The IOMMU mappings are torn down
+when the domain is destroyed, but the other actions go on to cause
+trouble later.  For example, the iommu->domain_list can be empty if we
+only have a non-IOMMU backed mdev attached.  We don't currently check
+if the list is empty before getting the first entry in the list, which
+leads to a bogus domain pointer.  If a vfio_dma entry is erroneously
+marked as iommu_mapped, we'll attempt to use that bogus pointer to
+retrieve the existing physical page addresses.
+
+This is the scenario that uncovered this issue, attempting to hot-add
+a vfio-pci device to a container with an existing mdev device and DMA
+mappings, one of which could not be pinned, causing a failure adding
+the new group to the existing container and setting the conditions
+for a subsequent attempt to explode.
+
+To resolve this, we can first check if the domain_list is empty so
+that we can reject replay of a bogus domain, should we ever encounter
+this inconsistent state again in the future.  The real fix though is
+to add the necessary unwind support, which means cleaning up the
+current pinning if an IOMMU mapping fails, then walking back through
+the r-b tree of DMA entries, reading from the IOMMU which ranges are
+mapped, and unmapping and unpinning those ranges.  To be able to do
+this, we also defer marking the DMA entry as IOMMU mapped until all
+entries are processed, in order to allow the unwind to know the
+disposition of each entry.
+
+Fixes: a54eb55045ae ("vfio iommu type1: Add support for mediated devices")
+Reported-by: Zhiyi Guo <zhguo@redhat.com>
+Tested-by: Zhiyi Guo <zhguo@redhat.com>
+Reviewed-by: Cornelia Huck <cohuck@redhat.com>
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/vfio_iommu_type1.c | 71 ++++++++++++++++++++++++++++++---
+ 1 file changed, 66 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
+index 35a3750a6ddd3..f22425501bc16 100644
+--- a/drivers/vfio/vfio_iommu_type1.c
++++ b/drivers/vfio/vfio_iommu_type1.c
+@@ -1086,13 +1086,16 @@ static int vfio_bus_type(struct device *dev, void *data)
+ static int vfio_iommu_replay(struct vfio_iommu *iommu,
+                            struct vfio_domain *domain)
+ {
+-      struct vfio_domain *d;
++      struct vfio_domain *d = NULL;
+       struct rb_node *n;
+       unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+       int ret;
+       /* Arbitrarily pick the first domain in the list for lookups */
+-      d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
++      if (!list_empty(&iommu->domain_list))
++              d = list_first_entry(&iommu->domain_list,
++                                   struct vfio_domain, next);
++
+       n = rb_first(&iommu->dma_list);
+       for (; n; n = rb_next(n)) {
+@@ -1110,6 +1113,11 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
+                               phys_addr_t p;
+                               dma_addr_t i;
++                              if (WARN_ON(!d)) { /* mapped w/o a domain?! */
++                                      ret = -EINVAL;
++                                      goto unwind;
++                              }
++
+                               phys = iommu_iova_to_phys(d->domain, iova);
+                               if (WARN_ON(!phys)) {
+@@ -1139,7 +1147,7 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
+                               if (npage <= 0) {
+                                       WARN_ON(!npage);
+                                       ret = (int)npage;
+-                                      return ret;
++                                      goto unwind;
+                               }
+                               phys = pfn << PAGE_SHIFT;
+@@ -1148,14 +1156,67 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
+                       ret = iommu_map(domain->domain, iova, phys,
+                                       size, dma->prot | domain->prot);
+-                      if (ret)
+-                              return ret;
++                      if (ret) {
++                              if (!dma->iommu_mapped)
++                                      vfio_unpin_pages_remote(dma, iova,
++                                                      phys >> PAGE_SHIFT,
++                                                      size >> PAGE_SHIFT,
++                                                      true);
++                              goto unwind;
++                      }
+                       iova += size;
+               }
++      }
++
++      /* All dmas are now mapped, defer to second tree walk for unwind */
++      for (n = rb_first(&iommu->dma_list); n; n = rb_next(n)) {
++              struct vfio_dma *dma = rb_entry(n, struct vfio_dma, node);
++
+               dma->iommu_mapped = true;
+       }
++
+       return 0;
++
++unwind:
++      for (; n; n = rb_prev(n)) {
++              struct vfio_dma *dma = rb_entry(n, struct vfio_dma, node);
++              dma_addr_t iova;
++
++              if (dma->iommu_mapped) {
++                      iommu_unmap(domain->domain, dma->iova, dma->size);
++                      continue;
++              }
++
++              iova = dma->iova;
++              while (iova < dma->iova + dma->size) {
++                      phys_addr_t phys, p;
++                      size_t size;
++                      dma_addr_t i;
++
++                      phys = iommu_iova_to_phys(domain->domain, iova);
++                      if (!phys) {
++                              iova += PAGE_SIZE;
++                              continue;
++                      }
++
++                      size = PAGE_SIZE;
++                      p = phys + size;
++                      i = iova + size;
++                      while (i < dma->iova + dma->size &&
++                             p == iommu_iova_to_phys(domain->domain, i)) {
++                              size += PAGE_SIZE;
++                              p += PAGE_SIZE;
++                              i += PAGE_SIZE;
++                      }
++
++                      iommu_unmap(domain->domain, iova, size);
++                      vfio_unpin_pages_remote(dma, iova, phys >> PAGE_SHIFT,
++                                              size >> PAGE_SHIFT, true);
++              }
++      }
++
++      return ret;
+ }
+ /*
+-- 
+2.25.1
+