]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Mon, 29 May 2023 02:43:52 +0000 (22:43 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 29 May 2023 02:43:52 +0000 (22:43 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
14 files changed:
queue-5.15/bpf-fix-a-memory-leak-in-the-lru-and-lru_percpu-hash.patch [new file with mode: 0644]
queue-5.15/net-mlx5-devcom-only-supports-2-ports.patch [new file with mode: 0644]
queue-5.15/net-mlx5-devcom-serialize-devcom-registration.patch [new file with mode: 0644]
queue-5.15/net-mlx5e-fix-deadlock-in-tc-route-query-code.patch [new file with mode: 0644]
queue-5.15/net-phy-mscc-enable-vsc8501-2-rgmii-rx-clock.patch [new file with mode: 0644]
queue-5.15/platform-x86-isst-punit-device-mapping-with-sub-numa.patch [new file with mode: 0644]
queue-5.15/platform-x86-isst-remove-8-socket-limit.patch [new file with mode: 0644]
queue-5.15/power-supply-bq24190-call-power_supply_changed-after.patch [new file with mode: 0644]
queue-5.15/power-supply-bq27xxx-after-charger-plug-in-out-wait-.patch [new file with mode: 0644]
queue-5.15/power-supply-bq27xxx-ensure-power_supply_changed-is-.patch [new file with mode: 0644]
queue-5.15/power-supply-bq27xxx-expose-battery-data-when-ci-1.patch [new file with mode: 0644]
queue-5.15/power-supply-bq27xxx-move-bq27xxx_battery_update-dow.patch [new file with mode: 0644]
queue-5.15/power-supply-core-refactor-power_supply_set_input_cu.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/bpf-fix-a-memory-leak-in-the-lru-and-lru_percpu-hash.patch b/queue-5.15/bpf-fix-a-memory-leak-in-the-lru-and-lru_percpu-hash.patch
new file mode 100644 (file)
index 0000000..65f9551
--- /dev/null
@@ -0,0 +1,68 @@
+From 7d3cab3c9ea91039c0cbfb88539e837a7b3ce8d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 May 2023 15:45:58 +0000
+Subject: bpf: fix a memory leak in the LRU and LRU_PERCPU hash maps
+
+From: Anton Protopopov <aspsk@isovalent.com>
+
+[ Upstream commit b34ffb0c6d23583830f9327864b9c1f486003305 ]
+
+The LRU and LRU_PERCPU maps allocate a new element on update before locking the
+target hash table bucket. Right after that the maps try to lock the bucket.
+If this fails, then maps return -EBUSY to the caller without releasing the
+allocated element. This makes the element untracked: it doesn't belong to
+either of free lists, and it doesn't belong to the hash table, so can't be
+re-used; this eventually leads to the permanent -ENOMEM on LRU map updates,
+which is unexpected. Fix this by returning the element to the local free list
+if bucket locking fails.
+
+Fixes: 20b6cc34ea74 ("bpf: Avoid hashtab deadlock with map_locked")
+Signed-off-by: Anton Protopopov <aspsk@isovalent.com>
+Link: https://lore.kernel.org/r/20230522154558.2166815-1-aspsk@isovalent.com
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/hashtab.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
+index 10b37773d9e47..a63c68f5945cd 100644
+--- a/kernel/bpf/hashtab.c
++++ b/kernel/bpf/hashtab.c
+@@ -1165,7 +1165,7 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
+       ret = htab_lock_bucket(htab, b, hash, &flags);
+       if (ret)
+-              return ret;
++              goto err_lock_bucket;
+       l_old = lookup_elem_raw(head, hash, key, key_size);
+@@ -1186,6 +1186,7 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
+ err:
+       htab_unlock_bucket(htab, b, hash, flags);
++err_lock_bucket:
+       if (ret)
+               htab_lru_push_free(htab, l_new);
+       else if (l_old)
+@@ -1288,7 +1289,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
+       ret = htab_lock_bucket(htab, b, hash, &flags);
+       if (ret)
+-              return ret;
++              goto err_lock_bucket;
+       l_old = lookup_elem_raw(head, hash, key, key_size);
+@@ -1311,6 +1312,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
+       ret = 0;
+ err:
+       htab_unlock_bucket(htab, b, hash, flags);
++err_lock_bucket:
+       if (l_new)
+               bpf_lru_push_free(&htab->lru, &l_new->lru_node);
+       return ret;
+-- 
+2.39.2
+
diff --git a/queue-5.15/net-mlx5-devcom-only-supports-2-ports.patch b/queue-5.15/net-mlx5-devcom-only-supports-2-ports.patch
new file mode 100644 (file)
index 0000000..ebec66a
--- /dev/null
@@ -0,0 +1,109 @@
+From 0f37bfd1d8a091aaa32eb5e028e9f86d68474dd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Feb 2022 12:23:34 +0000
+Subject: net/mlx5: devcom only supports 2 ports
+
+From: Mark Bloch <mbloch@nvidia.com>
+
+[ Upstream commit 8a6e75e5f57e9ac82268d9bfca3403598d9d0292 ]
+
+Devcom API is intended to be used between 2 devices only add this
+implied assumption into the code and check when it's no true.
+
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Maor Gottlieb <maorg@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Stable-dep-of: 691c041bf208 ("net/mlx5e: Fix deadlock in tc route query code")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/lib/devcom.c | 16 +++++++++-------
+ .../net/ethernet/mellanox/mlx5/core/lib/devcom.h |  2 ++
+ 2 files changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+index abd066e952286..617eea1b1701b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+@@ -14,7 +14,7 @@ static LIST_HEAD(devcom_list);
+ struct mlx5_devcom_component {
+       struct {
+               void *data;
+-      } device[MLX5_MAX_PORTS];
++      } device[MLX5_DEVCOM_PORTS_SUPPORTED];
+       mlx5_devcom_event_handler_t handler;
+       struct rw_semaphore sem;
+@@ -25,7 +25,7 @@ struct mlx5_devcom_list {
+       struct list_head list;
+       struct mlx5_devcom_component components[MLX5_DEVCOM_NUM_COMPONENTS];
+-      struct mlx5_core_dev *devs[MLX5_MAX_PORTS];
++      struct mlx5_core_dev *devs[MLX5_DEVCOM_PORTS_SUPPORTED];
+ };
+ struct mlx5_devcom {
+@@ -74,13 +74,15 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
+       if (!mlx5_core_is_pf(dev))
+               return NULL;
++      if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
++              return NULL;
+       sguid0 = mlx5_query_nic_system_image_guid(dev);
+       list_for_each_entry(iter, &devcom_list, list) {
+               struct mlx5_core_dev *tmp_dev = NULL;
+               idx = -1;
+-              for (i = 0; i < MLX5_MAX_PORTS; i++) {
++              for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
+                       if (iter->devs[i])
+                               tmp_dev = iter->devs[i];
+                       else
+@@ -135,11 +137,11 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
+       kfree(devcom);
+-      for (i = 0; i < MLX5_MAX_PORTS; i++)
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (priv->devs[i])
+                       break;
+-      if (i != MLX5_MAX_PORTS)
++      if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
+               return;
+       list_del(&priv->list);
+@@ -192,7 +194,7 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
+       comp = &devcom->priv->components[id];
+       down_write(&comp->sem);
+-      for (i = 0; i < MLX5_MAX_PORTS; i++)
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (i != devcom->idx && comp->device[i].data) {
+                       err = comp->handler(event, comp->device[i].data,
+                                           event_data);
+@@ -240,7 +242,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
+               return NULL;
+       }
+-      for (i = 0; i < MLX5_MAX_PORTS; i++)
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (i != devcom->idx)
+                       break;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+index 939d5bf1581b5..94313c18bb647 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+@@ -6,6 +6,8 @@
+ #include <linux/mlx5/driver.h>
++#define MLX5_DEVCOM_PORTS_SUPPORTED 2
++
+ enum mlx5_devcom_components {
+       MLX5_DEVCOM_ESW_OFFLOADS,
+-- 
+2.39.2
+
diff --git a/queue-5.15/net-mlx5-devcom-serialize-devcom-registration.patch b/queue-5.15/net-mlx5-devcom-serialize-devcom-registration.patch
new file mode 100644 (file)
index 0000000..2cbca9a
--- /dev/null
@@ -0,0 +1,100 @@
+From c60ed581b95c9bc1797e88519e9f7279b3dd69a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 May 2023 13:36:42 +0300
+Subject: net/mlx5: Devcom, serialize devcom registration
+
+From: Shay Drory <shayd@nvidia.com>
+
+[ Upstream commit 1f893f57a3bf9fe1f4bcb25b55aea7f7f9712fe7 ]
+
+From one hand, mlx5 driver is allowing to probe PFs in parallel.
+From the other hand, devcom, which is a share resource between PFs, is
+registered without any lock. This might resulted in memory problems.
+
+Hence, use the global mlx5_dev_list_lock in order to serialize devcom
+registration.
+
+Fixes: fadd59fc50d0 ("net/mlx5: Introduce inter-device communication mechanism")
+Signed-off-by: Shay Drory <shayd@nvidia.com>
+Reviewed-by: Mark Bloch <mbloch@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/lib/devcom.c  | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+index 8f978491dd32f..b7d779d08d837 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+@@ -3,6 +3,7 @@
+ #include <linux/mlx5/vport.h>
+ #include "lib/devcom.h"
++#include "mlx5_core.h"
+ static LIST_HEAD(devcom_list);
+@@ -77,6 +78,7 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
+       if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
+               return NULL;
++      mlx5_dev_list_lock();
+       sguid0 = mlx5_query_nic_system_image_guid(dev);
+       list_for_each_entry(iter, &devcom_list, list) {
+               struct mlx5_core_dev *tmp_dev = NULL;
+@@ -102,8 +104,10 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
+       if (!priv) {
+               priv = mlx5_devcom_list_alloc();
+-              if (!priv)
+-                      return ERR_PTR(-ENOMEM);
++              if (!priv) {
++                      devcom = ERR_PTR(-ENOMEM);
++                      goto out;
++              }
+               idx = 0;
+               new_priv = true;
+@@ -114,12 +118,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
+       if (!devcom) {
+               if (new_priv)
+                       kfree(priv);
+-              return ERR_PTR(-ENOMEM);
++              devcom = ERR_PTR(-ENOMEM);
++              goto out;
+       }
+       if (new_priv)
+               list_add(&priv->list, &devcom_list);
+-
++out:
++      mlx5_dev_list_unlock();
+       return devcom;
+ }
+@@ -132,6 +138,7 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
+       if (IS_ERR_OR_NULL(devcom))
+               return;
++      mlx5_dev_list_lock();
+       priv = devcom->priv;
+       priv->devs[devcom->idx] = NULL;
+@@ -142,10 +149,12 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom)
+                       break;
+       if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
+-              return;
++              goto out;
+       list_del(&priv->list);
+       kfree(priv);
++out:
++      mlx5_dev_list_unlock();
+ }
+ void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
+-- 
+2.39.2
+
diff --git a/queue-5.15/net-mlx5e-fix-deadlock-in-tc-route-query-code.patch b/queue-5.15/net-mlx5e-fix-deadlock-in-tc-route-query-code.patch
new file mode 100644 (file)
index 0000000..0aa1d09
--- /dev/null
@@ -0,0 +1,363 @@
+From 4f7602f29c3d6d8024125b8ac5f6c0d0ed398285 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Mar 2023 14:20:51 +0200
+Subject: net/mlx5e: Fix deadlock in tc route query code
+
+From: Vlad Buslov <vladbu@nvidia.com>
+
+[ Upstream commit 691c041bf20899fc13c793f92ba61ab660fa3a30 ]
+
+Cited commit causes ABBA deadlock[0] when peer flows are created while
+holding the devcom rw semaphore. Due to peer flows offload implementation
+the lock is taken much higher up the call chain and there is no obvious way
+to easily fix the deadlock. Instead, since tc route query code needs the
+peer eswitch structure only to perform a lookup in xarray and doesn't
+perform any sleeping operations with it, refactor the code for lockless
+execution in following ways:
+
+- RCUify the devcom 'data' pointer. When resetting the pointer
+synchronously wait for RCU grace period before returning. This is fine
+since devcom is currently only used for synchronization of
+pairing/unpairing of eswitches which is rare and already expensive as-is.
+
+- Wrap all usages of 'paired' boolean in {READ|WRITE}_ONCE(). The flag has
+already been used in some unlocked contexts without proper
+annotations (e.g. users of mlx5_devcom_is_paired() function), but it wasn't
+an issue since all relevant code paths checked it again after obtaining the
+devcom semaphore. Now it is also used by mlx5_devcom_get_peer_data_rcu() as
+"best effort" check to return NULL when devcom is being unpaired. Note that
+while RCU read lock doesn't prevent the unpaired flag from being changed
+concurrently it still guarantees that reader can continue to use 'data'.
+
+- Refactor mlx5e_tc_query_route_vport() function to use new
+mlx5_devcom_get_peer_data_rcu() API which fixes the deadlock.
+
+[0]:
+
+[  164.599612] ======================================================
+[  164.600142] WARNING: possible circular locking dependency detected
+[  164.600667] 6.3.0-rc3+ #1 Not tainted
+[  164.601021] ------------------------------------------------------
+[  164.601557] handler1/3456 is trying to acquire lock:
+[  164.601998] ffff88811f1714b0 (&esw->offloads.encap_tbl_lock){+.+.}-{3:3}, at: mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.603078]
+               but task is already holding lock:
+[  164.603617] ffff88810137fc98 (&comp->sem){++++}-{3:3}, at: mlx5_devcom_get_peer_data+0x37/0x80 [mlx5_core]
+[  164.604459]
+               which lock already depends on the new lock.
+
+[  164.605190]
+               the existing dependency chain (in reverse order) is:
+[  164.605848]
+               -> #1 (&comp->sem){++++}-{3:3}:
+[  164.606380]        down_read+0x39/0x50
+[  164.606772]        mlx5_devcom_get_peer_data+0x37/0x80 [mlx5_core]
+[  164.607336]        mlx5e_tc_query_route_vport+0x86/0xc0 [mlx5_core]
+[  164.607914]        mlx5e_tc_tun_route_lookup+0x1a4/0x1d0 [mlx5_core]
+[  164.608495]        mlx5e_attach_decap_route+0xc6/0x1e0 [mlx5_core]
+[  164.609063]        mlx5e_tc_add_fdb_flow+0x1ea/0x360 [mlx5_core]
+[  164.609627]        __mlx5e_add_fdb_flow+0x2d2/0x430 [mlx5_core]
+[  164.610175]        mlx5e_configure_flower+0x952/0x1a20 [mlx5_core]
+[  164.610741]        tc_setup_cb_add+0xd4/0x200
+[  164.611146]        fl_hw_replace_filter+0x14c/0x1f0 [cls_flower]
+[  164.611661]        fl_change+0xc95/0x18a0 [cls_flower]
+[  164.612116]        tc_new_tfilter+0x3fc/0xd20
+[  164.612516]        rtnetlink_rcv_msg+0x418/0x5b0
+[  164.612936]        netlink_rcv_skb+0x54/0x100
+[  164.613339]        netlink_unicast+0x190/0x250
+[  164.613746]        netlink_sendmsg+0x245/0x4a0
+[  164.614150]        sock_sendmsg+0x38/0x60
+[  164.614522]        ____sys_sendmsg+0x1d0/0x1e0
+[  164.614934]        ___sys_sendmsg+0x80/0xc0
+[  164.615320]        __sys_sendmsg+0x51/0x90
+[  164.615701]        do_syscall_64+0x3d/0x90
+[  164.616083]        entry_SYSCALL_64_after_hwframe+0x46/0xb0
+[  164.616568]
+               -> #0 (&esw->offloads.encap_tbl_lock){+.+.}-{3:3}:
+[  164.617210]        __lock_acquire+0x159e/0x26e0
+[  164.617638]        lock_acquire+0xc2/0x2a0
+[  164.618018]        __mutex_lock+0x92/0xcd0
+[  164.618401]        mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.618943]        post_process_attr+0x153/0x2d0 [mlx5_core]
+[  164.619471]        mlx5e_tc_add_fdb_flow+0x164/0x360 [mlx5_core]
+[  164.620021]        __mlx5e_add_fdb_flow+0x2d2/0x430 [mlx5_core]
+[  164.620564]        mlx5e_configure_flower+0xe33/0x1a20 [mlx5_core]
+[  164.621125]        tc_setup_cb_add+0xd4/0x200
+[  164.621531]        fl_hw_replace_filter+0x14c/0x1f0 [cls_flower]
+[  164.622047]        fl_change+0xc95/0x18a0 [cls_flower]
+[  164.622500]        tc_new_tfilter+0x3fc/0xd20
+[  164.622906]        rtnetlink_rcv_msg+0x418/0x5b0
+[  164.623324]        netlink_rcv_skb+0x54/0x100
+[  164.623727]        netlink_unicast+0x190/0x250
+[  164.624138]        netlink_sendmsg+0x245/0x4a0
+[  164.624544]        sock_sendmsg+0x38/0x60
+[  164.624919]        ____sys_sendmsg+0x1d0/0x1e0
+[  164.625340]        ___sys_sendmsg+0x80/0xc0
+[  164.625731]        __sys_sendmsg+0x51/0x90
+[  164.626117]        do_syscall_64+0x3d/0x90
+[  164.626502]        entry_SYSCALL_64_after_hwframe+0x46/0xb0
+[  164.626995]
+               other info that might help us debug this:
+
+[  164.627725]  Possible unsafe locking scenario:
+
+[  164.628268]        CPU0                    CPU1
+[  164.628683]        ----                    ----
+[  164.629098]   lock(&comp->sem);
+[  164.629421]                                lock(&esw->offloads.encap_tbl_lock);
+[  164.630066]                                lock(&comp->sem);
+[  164.630555]   lock(&esw->offloads.encap_tbl_lock);
+[  164.630993]
+                *** DEADLOCK ***
+
+[  164.631575] 3 locks held by handler1/3456:
+[  164.631962]  #0: ffff888124b75130 (&block->cb_lock){++++}-{3:3}, at: tc_setup_cb_add+0x5b/0x200
+[  164.632703]  #1: ffff888116e512b8 (&esw->mode_lock){++++}-{3:3}, at: mlx5_esw_hold+0x39/0x50 [mlx5_core]
+[  164.633552]  #2: ffff88810137fc98 (&comp->sem){++++}-{3:3}, at: mlx5_devcom_get_peer_data+0x37/0x80 [mlx5_core]
+[  164.634435]
+               stack backtrace:
+[  164.634883] CPU: 17 PID: 3456 Comm: handler1 Not tainted 6.3.0-rc3+ #1
+[  164.635431] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+[  164.636340] Call Trace:
+[  164.636616]  <TASK>
+[  164.636863]  dump_stack_lvl+0x47/0x70
+[  164.637217]  check_noncircular+0xfe/0x110
+[  164.637601]  __lock_acquire+0x159e/0x26e0
+[  164.637977]  ? mlx5_cmd_set_fte+0x5b0/0x830 [mlx5_core]
+[  164.638472]  lock_acquire+0xc2/0x2a0
+[  164.638828]  ? mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.639339]  ? lock_is_held_type+0x98/0x110
+[  164.639728]  __mutex_lock+0x92/0xcd0
+[  164.640074]  ? mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.640576]  ? __lock_acquire+0x382/0x26e0
+[  164.640958]  ? mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.641468]  ? mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.641965]  mlx5e_attach_encap+0xd8/0x8b0 [mlx5_core]
+[  164.642454]  ? lock_release+0xbf/0x240
+[  164.642819]  post_process_attr+0x153/0x2d0 [mlx5_core]
+[  164.643318]  mlx5e_tc_add_fdb_flow+0x164/0x360 [mlx5_core]
+[  164.643835]  __mlx5e_add_fdb_flow+0x2d2/0x430 [mlx5_core]
+[  164.644340]  mlx5e_configure_flower+0xe33/0x1a20 [mlx5_core]
+[  164.644862]  ? lock_acquire+0xc2/0x2a0
+[  164.645219]  tc_setup_cb_add+0xd4/0x200
+[  164.645588]  fl_hw_replace_filter+0x14c/0x1f0 [cls_flower]
+[  164.646067]  fl_change+0xc95/0x18a0 [cls_flower]
+[  164.646488]  tc_new_tfilter+0x3fc/0xd20
+[  164.646861]  ? tc_del_tfilter+0x810/0x810
+[  164.647236]  rtnetlink_rcv_msg+0x418/0x5b0
+[  164.647621]  ? rtnl_setlink+0x160/0x160
+[  164.647982]  netlink_rcv_skb+0x54/0x100
+[  164.648348]  netlink_unicast+0x190/0x250
+[  164.648722]  netlink_sendmsg+0x245/0x4a0
+[  164.649090]  sock_sendmsg+0x38/0x60
+[  164.649434]  ____sys_sendmsg+0x1d0/0x1e0
+[  164.649804]  ? copy_msghdr_from_user+0x6d/0xa0
+[  164.650213]  ___sys_sendmsg+0x80/0xc0
+[  164.650563]  ? lock_acquire+0xc2/0x2a0
+[  164.650926]  ? lock_acquire+0xc2/0x2a0
+[  164.651286]  ? __fget_files+0x5/0x190
+[  164.651644]  ? find_held_lock+0x2b/0x80
+[  164.652006]  ? __fget_files+0xb9/0x190
+[  164.652365]  ? lock_release+0xbf/0x240
+[  164.652723]  ? __fget_files+0xd3/0x190
+[  164.653079]  __sys_sendmsg+0x51/0x90
+[  164.653435]  do_syscall_64+0x3d/0x90
+[  164.653784]  entry_SYSCALL_64_after_hwframe+0x46/0xb0
+[  164.654229] RIP: 0033:0x7f378054f8bd
+[  164.654577] Code: 28 89 54 24 1c 48 89 74 24 10 89 7c 24 08 e8 6a c3 f4 ff 8b 54 24 1c 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 33 44 89 c7 48 89 44 24 08 e8 be c3 f4 ff 48
+[  164.656041] RSP: 002b:00007f377fa114b0 EFLAGS: 00000293 ORIG_RAX: 000000000000002e
+[  164.656701] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f378054f8bd
+[  164.657297] RDX: 0000000000000000 RSI: 00007f377fa11540 RDI: 0000000000000014
+[  164.657885] RBP: 00007f377fa12278 R08: 0000000000000000 R09: 000000000000015c
+[  164.658472] R10: 00007f377fa123d0 R11: 0000000000000293 R12: 0000560962d99bd0
+[  164.665317] R13: 0000000000000000 R14: 0000560962d99bd0 R15: 00007f377fa11540
+
+Fixes: f9d196bd632b ("net/mlx5e: Use correct eswitch for stack devices with lag")
+Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
+Reviewed-by: Roi Dayan <roid@nvidia.com>
+Reviewed-by: Shay Drory <shayd@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/en_tc.c   | 19 ++++----
+ .../ethernet/mellanox/mlx5/core/lib/devcom.c  | 48 ++++++++++++++-----
+ .../ethernet/mellanox/mlx5/core/lib/devcom.h  |  1 +
+ 3 files changed, 48 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 9ea4281a55b81..5cef556223e2c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -1308,11 +1308,9 @@ bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_
+ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev, u16 *vport)
+ {
+       struct mlx5e_priv *out_priv, *route_priv;
+-      struct mlx5_devcom *devcom = NULL;
+       struct mlx5_core_dev *route_mdev;
+       struct mlx5_eswitch *esw;
+       u16 vhca_id;
+-      int err;
+       out_priv = netdev_priv(out_dev);
+       esw = out_priv->mdev->priv.eswitch;
+@@ -1321,6 +1319,9 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
+       vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id);
+       if (mlx5_lag_is_active(out_priv->mdev)) {
++              struct mlx5_devcom *devcom;
++              int err;
++
+               /* In lag case we may get devices from different eswitch instances.
+                * If we failed to get vport num, it means, mostly, that we on the wrong
+                * eswitch.
+@@ -1329,16 +1330,16 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro
+               if (err != -ENOENT)
+                       return err;
++              rcu_read_lock();
+               devcom = out_priv->mdev->priv.devcom;
+-              esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+-              if (!esw)
+-                      return -ENODEV;
++              esw = mlx5_devcom_get_peer_data_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
++              err = esw ? mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport) : -ENODEV;
++              rcu_read_unlock();
++
++              return err;
+       }
+-      err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+-      if (devcom)
+-              mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
+-      return err;
++      return mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport);
+ }
+ int mlx5e_tc_add_flow_mod_hdr(struct mlx5e_priv *priv,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+index 617eea1b1701b..8f978491dd32f 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+@@ -13,7 +13,7 @@ static LIST_HEAD(devcom_list);
+ struct mlx5_devcom_component {
+       struct {
+-              void *data;
++              void __rcu *data;
+       } device[MLX5_DEVCOM_PORTS_SUPPORTED];
+       mlx5_devcom_event_handler_t handler;
+@@ -163,7 +163,7 @@ void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
+       comp = &devcom->priv->components[id];
+       down_write(&comp->sem);
+       comp->handler = handler;
+-      comp->device[devcom->idx].data = data;
++      rcu_assign_pointer(comp->device[devcom->idx].data, data);
+       up_write(&comp->sem);
+ }
+@@ -177,8 +177,9 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
+       comp = &devcom->priv->components[id];
+       down_write(&comp->sem);
+-      comp->device[devcom->idx].data = NULL;
++      RCU_INIT_POINTER(comp->device[devcom->idx].data, NULL);
+       up_write(&comp->sem);
++      synchronize_rcu();
+ }
+ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
+@@ -194,12 +195,15 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
+       comp = &devcom->priv->components[id];
+       down_write(&comp->sem);
+-      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+-              if (i != devcom->idx && comp->device[i].data) {
+-                      err = comp->handler(event, comp->device[i].data,
+-                                          event_data);
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
++              void *data = rcu_dereference_protected(comp->device[i].data,
++                                                     lockdep_is_held(&comp->sem));
++
++              if (i != devcom->idx && data) {
++                      err = comp->handler(event, data, event_data);
+                       break;
+               }
++      }
+       up_write(&comp->sem);
+       return err;
+@@ -214,7 +218,7 @@ void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
+       comp = &devcom->priv->components[id];
+       WARN_ON(!rwsem_is_locked(&comp->sem));
+-      comp->paired = paired;
++      WRITE_ONCE(comp->paired, paired);
+ }
+ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
+@@ -223,7 +227,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
+       if (IS_ERR_OR_NULL(devcom))
+               return false;
+-      return devcom->priv->components[id].paired;
++      return READ_ONCE(devcom->priv->components[id].paired);
+ }
+ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
+@@ -237,7 +241,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
+       comp = &devcom->priv->components[id];
+       down_read(&comp->sem);
+-      if (!comp->paired) {
++      if (!READ_ONCE(comp->paired)) {
+               up_read(&comp->sem);
+               return NULL;
+       }
+@@ -246,7 +250,29 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
+               if (i != devcom->idx)
+                       break;
+-      return comp->device[i].data;
++      return rcu_dereference_protected(comp->device[i].data, lockdep_is_held(&comp->sem));
++}
++
++void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id)
++{
++      struct mlx5_devcom_component *comp;
++      int i;
++
++      if (IS_ERR_OR_NULL(devcom))
++              return NULL;
++
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
++              if (i != devcom->idx)
++                      break;
++
++      comp = &devcom->priv->components[id];
++      /* This can change concurrently, however 'data' pointer will remain
++       * valid for the duration of RCU read section.
++       */
++      if (!READ_ONCE(comp->paired))
++              return NULL;
++
++      return rcu_dereference(comp->device[i].data);
+ }
+ void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+index 94313c18bb647..9a496f4722dad 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+@@ -41,6 +41,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
+ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
+                               enum mlx5_devcom_components id);
++void *mlx5_devcom_get_peer_data_rcu(struct mlx5_devcom *devcom, enum mlx5_devcom_components id);
+ void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom,
+                                  enum mlx5_devcom_components id);
+-- 
+2.39.2
+
diff --git a/queue-5.15/net-phy-mscc-enable-vsc8501-2-rgmii-rx-clock.patch b/queue-5.15/net-phy-mscc-enable-vsc8501-2-rgmii-rx-clock.patch
new file mode 100644 (file)
index 0000000..7a2591c
--- /dev/null
@@ -0,0 +1,134 @@
+From f43df598d867e5a7cad59723e565f87cb1acbc6a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 May 2023 17:31:08 +0200
+Subject: net: phy: mscc: enable VSC8501/2 RGMII RX clock
+
+From: David Epping <david.epping@missinglinkelectronics.com>
+
+[ Upstream commit 71460c9ec5c743e9ffffca3c874d66267c36345e ]
+
+By default the VSC8501 and VSC8502 RGMII/GMII/MII RX_CLK output is
+disabled. To allow packet forwarding towards the MAC it needs to be
+enabled.
+
+For other PHYs supported by this driver the clock output is enabled
+by default.
+
+Fixes: d3169863310d ("net: phy: mscc: add support for VSC8502")
+Signed-off-by: David Epping <david.epping@missinglinkelectronics.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/mscc/mscc.h      |  1 +
+ drivers/net/phy/mscc/mscc_main.c | 54 +++++++++++++++++---------------
+ 2 files changed, 29 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
+index a50235fdf7d99..055e4ca5b3b5c 100644
+--- a/drivers/net/phy/mscc/mscc.h
++++ b/drivers/net/phy/mscc/mscc.h
+@@ -179,6 +179,7 @@ enum rgmii_clock_delay {
+ #define VSC8502_RGMII_CNTL              20
+ #define VSC8502_RGMII_RX_DELAY_MASK     0x0070
+ #define VSC8502_RGMII_TX_DELAY_MASK     0x0007
++#define VSC8502_RGMII_RX_CLK_DISABLE    0x0800
+ #define MSCC_PHY_WOL_LOWER_MAC_ADDR     21
+ #define MSCC_PHY_WOL_MID_MAC_ADDR       22
+diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
+index 74f3aa752724f..cef43b1344a94 100644
+--- a/drivers/net/phy/mscc/mscc_main.c
++++ b/drivers/net/phy/mscc/mscc_main.c
+@@ -527,14 +527,27 @@ static int vsc85xx_mac_if_set(struct phy_device *phydev,
+  *  * 2.0 ns (which causes the data to be sampled at exactly half way between
+  *    clock transitions at 1000 Mbps) if delays should be enabled
+  */
+-static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
+-                                 u16 rgmii_rx_delay_mask,
+-                                 u16 rgmii_tx_delay_mask)
++static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl,
++                                   u16 rgmii_rx_delay_mask,
++                                   u16 rgmii_tx_delay_mask)
+ {
+       u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
+       u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
+       u16 reg_val = 0;
+-      int rc;
++      u16 mask = 0;
++      int rc = 0;
++
++      /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
++       * to be unset for all PHY modes, so do that as part of the paged
++       * register modification.
++       * For some family members (like VSC8530/31/40/41) this bit is reserved
++       * and read-only, and the RX clock is enabled by default.
++       */
++      if (rgmii_cntl == VSC8502_RGMII_CNTL)
++              mask |= VSC8502_RGMII_RX_CLK_DISABLE;
++
++      if (phy_interface_is_rgmii(phydev))
++              mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
+       mutex_lock(&phydev->lock);
+@@ -545,10 +558,9 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+               reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
+-      rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
+-                            rgmii_cntl,
+-                            rgmii_rx_delay_mask | rgmii_tx_delay_mask,
+-                            reg_val);
++      if (mask)
++              rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
++                                    rgmii_cntl, mask, reg_val);
+       mutex_unlock(&phydev->lock);
+@@ -557,19 +569,11 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
+ static int vsc85xx_default_config(struct phy_device *phydev)
+ {
+-      int rc;
+-
+       phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+-      if (phy_interface_mode_is_rgmii(phydev->interface)) {
+-              rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL,
+-                                           VSC8502_RGMII_RX_DELAY_MASK,
+-                                           VSC8502_RGMII_TX_DELAY_MASK);
+-              if (rc)
+-                      return rc;
+-      }
+-
+-      return 0;
++      return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL,
++                                       VSC8502_RGMII_RX_DELAY_MASK,
++                                       VSC8502_RGMII_TX_DELAY_MASK);
+ }
+ static int vsc85xx_get_tunable(struct phy_device *phydev,
+@@ -1766,13 +1770,11 @@ static int vsc8584_config_init(struct phy_device *phydev)
+       if (ret)
+               return ret;
+-      if (phy_interface_is_rgmii(phydev)) {
+-              ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL,
+-                                            VSC8572_RGMII_RX_DELAY_MASK,
+-                                            VSC8572_RGMII_TX_DELAY_MASK);
+-              if (ret)
+-                      return ret;
+-      }
++      ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL,
++                                      VSC8572_RGMII_RX_DELAY_MASK,
++                                      VSC8572_RGMII_TX_DELAY_MASK);
++      if (ret)
++              return ret;
+       ret = genphy_soft_reset(phydev);
+       if (ret)
+-- 
+2.39.2
+
diff --git a/queue-5.15/platform-x86-isst-punit-device-mapping-with-sub-numa.patch b/queue-5.15/platform-x86-isst-punit-device-mapping-with-sub-numa.patch
new file mode 100644 (file)
index 0000000..a341fbc
--- /dev/null
@@ -0,0 +1,150 @@
+From 32ce098fd779c25409930f618d9ba156d40095ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jun 2022 12:48:17 -0700
+Subject: platform/x86: ISST: PUNIT device mapping with Sub-NUMA clustering
+
+From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+
+[ Upstream commit 9a1aac8a96dc014bec49806a7a964bf2fdbd315f ]
+
+On a multiple package system using Sub-NUMA clustering, there is an issue
+in mapping Linux CPU number to PUNIT PCI device when manufacturer decided
+to reuse the PCI bus number across packages. Bus number can be reused as
+long as they are in different domain or segment. In this case some CPU
+will fail to find a PCI device to issue SST requests.
+
+When bus numbers are reused across CPU packages, we are using proximity
+information by matching CPU numa node id to PUNIT PCI device numa node
+id. But on a package there can be only one PUNIT PCI device, but multiple
+numa nodes (one for each sub cluster). So, the numa node ID of the PUNIT
+PCI device can only match with one numa node id of CPUs in a sub cluster
+in the package.
+
+Since there can be only one PUNIT PCI device per package, if we match
+with numa node id of any sub cluster in that package, we can use that
+mapping for any CPU in that package. So, store the match information
+in a per package data structure and return the information when there
+is no match.
+
+While here, use defines for max bus number instead of hardcoding.
+
+Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Link: https://lore.kernel.org/r/20220629194817.2418240-1-srinivas.pandruvada@linux.intel.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Stable-dep-of: bbb320bfe2c3 ("platform/x86: ISST: Remove 8 socket limit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../intel/speed_select_if/isst_if_common.c    | 39 +++++++++++++++----
+ 1 file changed, 32 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+index e8424e70d81d2..fd102678c75f6 100644
+--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
++++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+@@ -277,29 +277,38 @@ static int isst_if_get_platform_info(void __user *argp)
+       return 0;
+ }
++#define ISST_MAX_BUS_NUMBER   2
+ struct isst_if_cpu_info {
+       /* For BUS 0 and BUS 1 only, which we need for PUNIT interface */
+-      int bus_info[2];
+-      struct pci_dev *pci_dev[2];
++      int bus_info[ISST_MAX_BUS_NUMBER];
++      struct pci_dev *pci_dev[ISST_MAX_BUS_NUMBER];
+       int punit_cpu_id;
+       int numa_node;
+ };
++struct isst_if_pkg_info {
++      struct pci_dev *pci_dev[ISST_MAX_BUS_NUMBER];
++};
++
+ static struct isst_if_cpu_info *isst_cpu_info;
++static struct isst_if_pkg_info *isst_pkg_info;
++
+ #define ISST_MAX_PCI_DOMAINS  8
+ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
+ {
+       struct pci_dev *matched_pci_dev = NULL;
+       struct pci_dev *pci_dev = NULL;
+-      int no_matches = 0;
++      int no_matches = 0, pkg_id;
+       int i, bus_number;
+-      if (bus_no < 0 || bus_no > 1 || cpu < 0 || cpu >= nr_cpu_ids ||
+-          cpu >= num_possible_cpus())
++      if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
++          cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
+               return NULL;
++      pkg_id = topology_physical_package_id(cpu);
++
+       bus_number = isst_cpu_info[cpu].bus_info[bus_no];
+       if (bus_number < 0)
+               return NULL;
+@@ -324,6 +333,8 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
+               }
+               if (node == isst_cpu_info[cpu].numa_node) {
++                      isst_pkg_info[pkg_id].pci_dev[bus_no] = _pci_dev;
++
+                       pci_dev = _pci_dev;
+                       break;
+               }
+@@ -342,6 +353,10 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
+       if (!pci_dev && no_matches == 1)
+               pci_dev = matched_pci_dev;
++      /* Return pci_dev pointer for any matched CPU in the package */
++      if (!pci_dev)
++              pci_dev = isst_pkg_info[pkg_id].pci_dev[bus_no];
++
+       return pci_dev;
+ }
+@@ -361,8 +376,8 @@ struct pci_dev *isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
+ {
+       struct pci_dev *pci_dev;
+-      if (bus_no < 0 || bus_no > 1 || cpu < 0 || cpu >= nr_cpu_ids ||
+-          cpu >= num_possible_cpus())
++      if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER  || cpu < 0 ||
++          cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
+               return NULL;
+       pci_dev = isst_cpu_info[cpu].pci_dev[bus_no];
+@@ -417,10 +432,19 @@ static int isst_if_cpu_info_init(void)
+       if (!isst_cpu_info)
+               return -ENOMEM;
++      isst_pkg_info = kcalloc(topology_max_packages(),
++                              sizeof(*isst_pkg_info),
++                              GFP_KERNEL);
++      if (!isst_pkg_info) {
++              kfree(isst_cpu_info);
++              return -ENOMEM;
++      }
++
+       ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+                               "platform/x86/isst-if:online",
+                               isst_if_cpu_online, NULL);
+       if (ret < 0) {
++              kfree(isst_pkg_info);
+               kfree(isst_cpu_info);
+               return ret;
+       }
+@@ -433,6 +457,7 @@ static int isst_if_cpu_info_init(void)
+ static void isst_if_cpu_info_exit(void)
+ {
+       cpuhp_remove_state(isst_if_online_id);
++      kfree(isst_pkg_info);
+       kfree(isst_cpu_info);
+ };
+-- 
+2.39.2
+
diff --git a/queue-5.15/platform-x86-isst-remove-8-socket-limit.patch b/queue-5.15/platform-x86-isst-remove-8-socket-limit.patch
new file mode 100644 (file)
index 0000000..f3c3f0a
--- /dev/null
@@ -0,0 +1,70 @@
+From 1a4170641f45352e73fcd2fd4bdc7eb498fee8ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 May 2023 11:04:20 -0500
+Subject: platform/x86: ISST: Remove 8 socket limit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Steve Wahl <steve.wahl@hpe.com>
+
+[ Upstream commit bbb320bfe2c3e9740fe89cfa0a7089b4e8bfc4ff ]
+
+Stop restricting the PCI search to a range of PCI domains fed to
+pci_get_domain_bus_and_slot().  Instead, use for_each_pci_dev() and
+look at all PCI domains in one pass.
+
+On systems with more than 8 sockets, this avoids error messages like
+"Information: Invalid level, Can't get TDP control information at
+specified levels on cpu 480" from the intel speed select utility.
+
+Fixes: aa2ddd242572 ("platform/x86: ISST: Use numa node id for cpu pci dev mapping")
+Signed-off-by: Steve Wahl <steve.wahl@hpe.com>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20230519160420.2588475-1-steve.wahl@hpe.com
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../x86/intel/speed_select_if/isst_if_common.c       | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+index fd102678c75f6..f6b32d31c5110 100644
+--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
++++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+@@ -294,14 +294,13 @@ struct isst_if_pkg_info {
+ static struct isst_if_cpu_info *isst_cpu_info;
+ static struct isst_if_pkg_info *isst_pkg_info;
+-#define ISST_MAX_PCI_DOMAINS  8
+-
+ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
+ {
+       struct pci_dev *matched_pci_dev = NULL;
+       struct pci_dev *pci_dev = NULL;
++      struct pci_dev *_pci_dev = NULL;
+       int no_matches = 0, pkg_id;
+-      int i, bus_number;
++      int bus_number;
+       if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
+           cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
+@@ -313,12 +312,11 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
+       if (bus_number < 0)
+               return NULL;
+-      for (i = 0; i < ISST_MAX_PCI_DOMAINS; ++i) {
+-              struct pci_dev *_pci_dev;
++      for_each_pci_dev(_pci_dev) {
+               int node;
+-              _pci_dev = pci_get_domain_bus_and_slot(i, bus_number, PCI_DEVFN(dev, fn));
+-              if (!_pci_dev)
++              if (_pci_dev->bus->number != bus_number ||
++                  _pci_dev->devfn != PCI_DEVFN(dev, fn))
+                       continue;
+               ++no_matches;
+-- 
+2.39.2
+
diff --git a/queue-5.15/power-supply-bq24190-call-power_supply_changed-after.patch b/queue-5.15/power-supply-bq24190-call-power_supply_changed-after.patch
new file mode 100644 (file)
index 0000000..67e34f1
--- /dev/null
@@ -0,0 +1,47 @@
+From 0e455263b8b1a134ef8b9e9b98501c20d37b85cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 20:23:41 +0200
+Subject: power: supply: bq24190: Call power_supply_changed() after updating
+ input current
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 77c2a3097d7029441e8a91aa0de1b4e5464593da ]
+
+The bq24192 model relies on external charger-type detection and once
+that is done the bq24190_charger code will update the input current.
+
+In this case, when the initial power_supply_changed() call is made
+from the interrupt handler, the input settings are 5V/0.5A which
+on many devices is not enough power to charge (while the device is on).
+
+On many devices the fuel-gauge relies in its external_power_changed
+callback to timely signal userspace about charging <-> discharging
+status changes. Add a power_supply_changed() call after updating
+the input current. This allows the fuel-gauge driver to timely recheck
+if the battery is charging after the new input current has been applied
+and then it can immediately notify userspace about this.
+
+Fixes: 18f8e6f695ac ("power: supply: bq24190_charger: Get input_current_limit from our supplier")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq24190_charger.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
+index 19537bd75013d..90ac5e59a5d6f 100644
+--- a/drivers/power/supply/bq24190_charger.c
++++ b/drivers/power/supply/bq24190_charger.c
+@@ -1213,6 +1213,7 @@ static void bq24190_input_current_limit_work(struct work_struct *work)
+       bq24190_charger_set_property(bdi->charger,
+                                    POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+                                    &val);
++      power_supply_changed(bdi->charger);
+ }
+ /* Sync the input-current-limit with our parent supply (if we have one) */
+-- 
+2.39.2
+
diff --git a/queue-5.15/power-supply-bq27xxx-after-charger-plug-in-out-wait-.patch b/queue-5.15/power-supply-bq27xxx-after-charger-plug-in-out-wait-.patch
new file mode 100644 (file)
index 0000000..f84d910
--- /dev/null
@@ -0,0 +1,41 @@
+From 07112bfee07128c0d44f8288dc37647d21dfcd0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 20:23:38 +0200
+Subject: power: supply: bq27xxx: After charger plug in/out wait 0.5s for
+ things to stabilize
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 59a99cd462fbdf71f4e845e09f37783035088b4f ]
+
+bq27xxx_external_power_changed() gets called when the charger is plugged
+in or out. Rather then immediately scheduling an update wait 0.5 seconds
+for things to stabilize, so that e.g. the (dis)charge current is stable
+when bq27xxx_battery_update() runs.
+
+Fixes: 740b755a3b34 ("bq27x00: Poll battery state")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq27xxx_battery.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
+index e6d67655732aa..ffb5f5c028223 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -2099,8 +2099,8 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
+ {
+       struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
+-      cancel_delayed_work_sync(&di->work);
+-      schedule_delayed_work(&di->work, 0);
++      /* After charger plug in/out wait 0.5s for things to stabilize */
++      mod_delayed_work(system_wq, &di->work, HZ / 2);
+ }
+ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
+-- 
+2.39.2
+
diff --git a/queue-5.15/power-supply-bq27xxx-ensure-power_supply_changed-is-.patch b/queue-5.15/power-supply-bq27xxx-ensure-power_supply_changed-is-.patch
new file mode 100644 (file)
index 0000000..4cb6b39
--- /dev/null
@@ -0,0 +1,98 @@
+From 35dfb547bb1a5458f9a9f6093b16890cb19ec9d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 20:23:37 +0200
+Subject: power: supply: bq27xxx: Ensure power_supply_changed() is called on
+ current sign changes
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 939a116142012926e25de0ea6b7e2f8d86a5f1b6 ]
+
+On gauges where the current register is signed, there is no charging
+flag in the flags register. So only checking flags will not result
+in power_supply_changed() getting called when e.g. a charger is plugged
+in and the current sign changes from negative (discharging) to
+positive (charging).
+
+This causes userspace's notion of the status to lag until userspace
+does a poll.
+
+And when a power_supply_leds.c LED trigger is used to indicate charging
+status with a LED, this LED will lag until the capacity percentage
+changes, which may take many minutes (because the LED trigger only is
+updated on power_supply_changed() calls).
+
+Fix this by calling bq27xxx_battery_current_and_status() on gauges with
+a signed current register and checking if the status has changed.
+
+Fixes: 297a533b3e62 ("bq27x00: Cache battery registers")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq27xxx_battery.c | 13 ++++++++++++-
+ include/linux/power/bq27xxx_battery.h  |  3 +++
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
+index 2fca4b9403ff9..e6d67655732aa 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1836,6 +1836,7 @@ static int bq27xxx_battery_current_and_status(
+ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+ {
++      union power_supply_propval status = di->last_status;
+       struct bq27xxx_reg_cache cache = {0, };
+       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
+@@ -1860,14 +1861,24 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+               if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+                       cache.cycle_count = bq27xxx_battery_read_cyct(di);
++              /*
++               * On gauges with signed current reporting the current must be
++               * checked to detect charging <-> discharging status changes.
++               */
++              if (!(di->opts & BQ27XXX_O_ZERO))
++                      bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
++
+               /* We only have to read charge design full once */
+               if (di->charge_design_full <= 0)
+                       di->charge_design_full = bq27xxx_battery_read_dcap(di);
+       }
+       if ((di->cache.capacity != cache.capacity) ||
+-          (di->cache.flags != cache.flags))
++          (di->cache.flags != cache.flags) ||
++          (di->last_status.intval != status.intval)) {
++              di->last_status.intval = status.intval;
+               power_supply_changed(di->bat);
++      }
+       if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
+               di->cache = cache;
+diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
+index e3322dad9c85c..7c8d65414a70a 100644
+--- a/include/linux/power/bq27xxx_battery.h
++++ b/include/linux/power/bq27xxx_battery.h
+@@ -2,6 +2,8 @@
+ #ifndef __LINUX_BQ27X00_BATTERY_H__
+ #define __LINUX_BQ27X00_BATTERY_H__
++#include <linux/power_supply.h>
++
+ enum bq27xxx_chip {
+       BQ27000 = 1, /* bq27000, bq27200 */
+       BQ27010, /* bq27010, bq27210 */
+@@ -70,6 +72,7 @@ struct bq27xxx_device_info {
+       int charge_design_full;
+       bool removed;
+       unsigned long last_update;
++      union power_supply_propval last_status;
+       struct delayed_work work;
+       struct power_supply *bat;
+       struct list_head list;
+-- 
+2.39.2
+
diff --git a/queue-5.15/power-supply-bq27xxx-expose-battery-data-when-ci-1.patch b/queue-5.15/power-supply-bq27xxx-expose-battery-data-when-ci-1.patch
new file mode 100644 (file)
index 0000000..183ca70
--- /dev/null
@@ -0,0 +1,129 @@
+From 4cd898f46dbc60506df9befb73d371e94b503d31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Apr 2022 14:30:59 +0200
+Subject: power: supply: bq27xxx: expose battery data when CI=1
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sicelo A. Mhlongo <absicsz@gmail.com>
+
+[ Upstream commit 68fdbe090c362e8be23890a7333d156e18c27781 ]
+
+When the Capacity Inaccurate flag is set, the chip still provides data
+about the battery, albeit inaccurate. Instead of discarding capacity
+values for CI=1, expose the stale data and use the
+POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED property to indicate that the
+values should be used with care.
+
+Reviewed-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Sicelo A. Mhlongo <absicsz@gmail.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Stable-dep-of: ff4c4a2a4437 ("power: supply: bq27xxx: Move bq27xxx_battery_update() down")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq27xxx_battery.c | 60 ++++++++++++--------------
+ 1 file changed, 27 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
+index 7334a8b8007e5..66199f1c1c5d1 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1572,14 +1572,6 @@ static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg)
+  */
+ static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di)
+ {
+-      int flags;
+-
+-      if (di->opts & BQ27XXX_O_ZERO) {
+-              flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true);
+-              if (flags >= 0 && (flags & BQ27000_FLAG_CI))
+-                      return -ENODATA;
+-      }
+-
+       return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC);
+ }
+@@ -1742,6 +1734,18 @@ static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags)
+               return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF);
+ }
++/*
++ * Returns true if reported battery capacity is inaccurate
++ */
++static bool bq27xxx_battery_capacity_inaccurate(struct bq27xxx_device_info *di,
++                                               u16 flags)
++{
++      if (di->opts & BQ27XXX_O_HAS_CI)
++              return (flags & BQ27000_FLAG_CI);
++      else
++              return false;
++}
++
+ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
+ {
+       /* Unlikely but important to return first */
+@@ -1751,6 +1755,8 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
+               return POWER_SUPPLY_HEALTH_COLD;
+       if (unlikely(bq27xxx_battery_dead(di, di->cache.flags)))
+               return POWER_SUPPLY_HEALTH_DEAD;
++      if (unlikely(bq27xxx_battery_capacity_inaccurate(di, di->cache.flags)))
++              return POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED;
+       return POWER_SUPPLY_HEALTH_GOOD;
+ }
+@@ -1758,7 +1764,6 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
+ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+ {
+       struct bq27xxx_reg_cache cache = {0, };
+-      bool has_ci_flag = di->opts & BQ27XXX_O_HAS_CI;
+       bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
+       cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
+@@ -1766,30 +1771,19 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+               cache.flags = -1; /* read error */
+       if (cache.flags >= 0) {
+               cache.temperature = bq27xxx_battery_read_temperature(di);
+-              if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) {
+-                      dev_info_once(di->dev, "battery is not calibrated! ignoring capacity values\n");
+-                      cache.capacity = -ENODATA;
+-                      cache.energy = -ENODATA;
+-                      cache.time_to_empty = -ENODATA;
+-                      cache.time_to_empty_avg = -ENODATA;
+-                      cache.time_to_full = -ENODATA;
+-                      cache.charge_full = -ENODATA;
+-                      cache.health = -ENODATA;
+-              } else {
+-                      if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+-                              cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+-                      if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+-                              cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+-                      if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+-                              cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+-
+-                      cache.charge_full = bq27xxx_battery_read_fcc(di);
+-                      cache.capacity = bq27xxx_battery_read_soc(di);
+-                      if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
+-                              cache.energy = bq27xxx_battery_read_energy(di);
+-                      di->cache.flags = cache.flags;
+-                      cache.health = bq27xxx_battery_read_health(di);
+-              }
++              if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
++                      cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
++              if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
++                      cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
++              if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
++                      cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
++
++              cache.charge_full = bq27xxx_battery_read_fcc(di);
++              cache.capacity = bq27xxx_battery_read_soc(di);
++              if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
++                      cache.energy = bq27xxx_battery_read_energy(di);
++              di->cache.flags = cache.flags;
++              cache.health = bq27xxx_battery_read_health(di);
+               if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+                       cache.cycle_count = bq27xxx_battery_read_cyct(di);
+-- 
+2.39.2
+
diff --git a/queue-5.15/power-supply-bq27xxx-move-bq27xxx_battery_update-dow.patch b/queue-5.15/power-supply-bq27xxx-move-bq27xxx_battery_update-dow.patch
new file mode 100644 (file)
index 0000000..30fec46
--- /dev/null
@@ -0,0 +1,168 @@
+From e1b3d51e657e8b3004766b04e6a321cad3bd0f51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 15 Apr 2023 20:23:36 +0200
+Subject: power: supply: bq27xxx: Move bq27xxx_battery_update() down
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit ff4c4a2a4437a6d03787c7aafb2617f20c3ef45f ]
+
+Move the bq27xxx_battery_update() functions to below
+the bq27xxx_battery_current_and_status() function.
+
+This is just moving a block of text, no functional changes.
+
+This is a preparation patch for making bq27xxx_battery_update() check
+the status and have it call power_supply_changed() on status changes.
+
+Fixes: 297a533b3e62 ("bq27x00: Cache battery registers")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq27xxx_battery.c | 122 ++++++++++++-------------
+ 1 file changed, 61 insertions(+), 61 deletions(-)
+
+diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
+index 66199f1c1c5d1..2fca4b9403ff9 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1761,67 +1761,6 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
+       return POWER_SUPPLY_HEALTH_GOOD;
+ }
+-static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+-{
+-      struct bq27xxx_reg_cache cache = {0, };
+-      bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
+-
+-      cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
+-      if ((cache.flags & 0xff) == 0xff)
+-              cache.flags = -1; /* read error */
+-      if (cache.flags >= 0) {
+-              cache.temperature = bq27xxx_battery_read_temperature(di);
+-              if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+-                      cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+-              if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+-                      cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+-              if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+-                      cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+-
+-              cache.charge_full = bq27xxx_battery_read_fcc(di);
+-              cache.capacity = bq27xxx_battery_read_soc(di);
+-              if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
+-                      cache.energy = bq27xxx_battery_read_energy(di);
+-              di->cache.flags = cache.flags;
+-              cache.health = bq27xxx_battery_read_health(di);
+-              if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+-                      cache.cycle_count = bq27xxx_battery_read_cyct(di);
+-
+-              /* We only have to read charge design full once */
+-              if (di->charge_design_full <= 0)
+-                      di->charge_design_full = bq27xxx_battery_read_dcap(di);
+-      }
+-
+-      if ((di->cache.capacity != cache.capacity) ||
+-          (di->cache.flags != cache.flags))
+-              power_supply_changed(di->bat);
+-
+-      if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
+-              di->cache = cache;
+-
+-      di->last_update = jiffies;
+-
+-      if (!di->removed && poll_interval > 0)
+-              mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
+-}
+-
+-void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+-{
+-      mutex_lock(&di->lock);
+-      bq27xxx_battery_update_unlocked(di);
+-      mutex_unlock(&di->lock);
+-}
+-EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
+-
+-static void bq27xxx_battery_poll(struct work_struct *work)
+-{
+-      struct bq27xxx_device_info *di =
+-                      container_of(work, struct bq27xxx_device_info,
+-                                   work.work);
+-
+-      bq27xxx_battery_update(di);
+-}
+-
+ static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags)
+ {
+       if (di->opts & BQ27XXX_O_ZERO)
+@@ -1895,6 +1834,67 @@ static int bq27xxx_battery_current_and_status(
+       return 0;
+ }
++static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
++{
++      struct bq27xxx_reg_cache cache = {0, };
++      bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
++
++      cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag);
++      if ((cache.flags & 0xff) == 0xff)
++              cache.flags = -1; /* read error */
++      if (cache.flags >= 0) {
++              cache.temperature = bq27xxx_battery_read_temperature(di);
++              if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
++                      cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
++              if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
++                      cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
++              if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
++                      cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
++
++              cache.charge_full = bq27xxx_battery_read_fcc(di);
++              cache.capacity = bq27xxx_battery_read_soc(di);
++              if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
++                      cache.energy = bq27xxx_battery_read_energy(di);
++              di->cache.flags = cache.flags;
++              cache.health = bq27xxx_battery_read_health(di);
++              if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
++                      cache.cycle_count = bq27xxx_battery_read_cyct(di);
++
++              /* We only have to read charge design full once */
++              if (di->charge_design_full <= 0)
++                      di->charge_design_full = bq27xxx_battery_read_dcap(di);
++      }
++
++      if ((di->cache.capacity != cache.capacity) ||
++          (di->cache.flags != cache.flags))
++              power_supply_changed(di->bat);
++
++      if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
++              di->cache = cache;
++
++      di->last_update = jiffies;
++
++      if (!di->removed && poll_interval > 0)
++              mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
++}
++
++void bq27xxx_battery_update(struct bq27xxx_device_info *di)
++{
++      mutex_lock(&di->lock);
++      bq27xxx_battery_update_unlocked(di);
++      mutex_unlock(&di->lock);
++}
++EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
++
++static void bq27xxx_battery_poll(struct work_struct *work)
++{
++      struct bq27xxx_device_info *di =
++                      container_of(work, struct bq27xxx_device_info,
++                                   work.work);
++
++      bq27xxx_battery_update(di);
++}
++
+ /*
+  * Get the average power in µW
+  * Return < 0 if something fails.
+-- 
+2.39.2
+
diff --git a/queue-5.15/power-supply-core-refactor-power_supply_set_input_cu.patch b/queue-5.15/power-supply-core-refactor-power_supply_set_input_cu.patch
new file mode 100644 (file)
index 0000000..c4fc4c2
--- /dev/null
@@ -0,0 +1,171 @@
+From c3156391121e1c14fd9da687c638ec0dc09b68c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Feb 2022 14:06:47 +0100
+Subject: power: supply: core: Refactor
+ power_supply_set_input_current_limit_from_supplier()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 2220af8ca61ae67de4ec3deec1c6395a2f65b9fd ]
+
+Some (USB) charger ICs have variants with USB D+ and D- pins to do their
+own builtin charger-type detection, like e.g. the bq24190 and bq25890 and
+also variants which lack this functionality, e.g. the bq24192 and bq25892.
+
+In case the charger-type; and thus the input-current-limit detection is
+done outside the charger IC then we need some way to communicate this to
+the charger IC. In the past extcon was used for this, but if the external
+detection does e.g. full USB PD negotiation then the extcon cable-types do
+not convey enough information.
+
+For these setups it was decided to model the external charging "brick"
+and the parameters negotiated with it as a power_supply class-device
+itself; and power_supply_set_input_current_limit_from_supplier() was
+introduced to allow drivers to get the input-current-limit this way.
+
+But in some cases psy drivers may want to know other properties, e.g. the
+bq25892 can do "quick-charge" negotiation by pulsing its current draw,
+but this should only be done if the usb_type psy-property of its supplier
+is set to DCP (and device-properties indicate the board allows higher
+voltages).
+
+Instead of adding extra helper functions for each property which
+a psy-driver wants to query from its supplier, refactor
+power_supply_set_input_current_limit_from_supplier() into a
+more generic power_supply_get_property_from_supplier() function.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Stable-dep-of: 77c2a3097d70 ("power: supply: bq24190: Call power_supply_changed() after updating input current")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/power/supply/bq24190_charger.c   | 12 ++++-
+ drivers/power/supply/power_supply_core.c | 57 +++++++++++++-----------
+ include/linux/power_supply.h             |  5 ++-
+ 3 files changed, 44 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
+index ebb5ba7f8bb63..19537bd75013d 100644
+--- a/drivers/power/supply/bq24190_charger.c
++++ b/drivers/power/supply/bq24190_charger.c
+@@ -1201,8 +1201,18 @@ static void bq24190_input_current_limit_work(struct work_struct *work)
+       struct bq24190_dev_info *bdi =
+               container_of(work, struct bq24190_dev_info,
+                            input_current_limit_work.work);
++      union power_supply_propval val;
++      int ret;
++
++      ret = power_supply_get_property_from_supplier(bdi->charger,
++                                                    POWER_SUPPLY_PROP_CURRENT_MAX,
++                                                    &val);
++      if (ret)
++              return;
+-      power_supply_set_input_current_limit_from_supplier(bdi->charger);
++      bq24190_charger_set_property(bdi->charger,
++                                   POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
++                                   &val);
+ }
+ /* Sync the input-current-limit with our parent supply (if we have one) */
+diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
+index 8161fad081a96..daf76d7885c05 100644
+--- a/drivers/power/supply/power_supply_core.c
++++ b/drivers/power/supply/power_supply_core.c
+@@ -375,46 +375,49 @@ int power_supply_is_system_supplied(void)
+ }
+ EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
+-static int __power_supply_get_supplier_max_current(struct device *dev,
+-                                                 void *data)
++struct psy_get_supplier_prop_data {
++      struct power_supply *psy;
++      enum power_supply_property psp;
++      union power_supply_propval *val;
++};
++
++static int __power_supply_get_supplier_property(struct device *dev, void *_data)
+ {
+-      union power_supply_propval ret = {0,};
+       struct power_supply *epsy = dev_get_drvdata(dev);
+-      struct power_supply *psy = data;
++      struct psy_get_supplier_prop_data *data = _data;
+-      if (__power_supply_is_supplied_by(epsy, psy))
+-              if (!epsy->desc->get_property(epsy,
+-                                            POWER_SUPPLY_PROP_CURRENT_MAX,
+-                                            &ret))
+-                      return ret.intval;
++      if (__power_supply_is_supplied_by(epsy, data->psy))
++              if (!epsy->desc->get_property(epsy, data->psp, data->val))
++                      return 1; /* Success */
+-      return 0;
++      return 0; /* Continue iterating */
+ }
+-int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy)
++int power_supply_get_property_from_supplier(struct power_supply *psy,
++                                          enum power_supply_property psp,
++                                          union power_supply_propval *val)
+ {
+-      union power_supply_propval val = {0,};
+-      int curr;
+-
+-      if (!psy->desc->set_property)
+-              return -EINVAL;
++      struct psy_get_supplier_prop_data data = {
++              .psy = psy,
++              .psp = psp,
++              .val = val,
++      };
++      int ret;
+       /*
+        * This function is not intended for use with a supply with multiple
+-       * suppliers, we simply pick the first supply to report a non 0
+-       * max-current.
++       * suppliers, we simply pick the first supply to report the psp.
+        */
+-      curr = class_for_each_device(power_supply_class, NULL, psy,
+-                                    __power_supply_get_supplier_max_current);
+-      if (curr <= 0)
+-              return (curr == 0) ? -ENODEV : curr;
+-
+-      val.intval = curr;
++      ret = class_for_each_device(power_supply_class, NULL, &data,
++                                  __power_supply_get_supplier_property);
++      if (ret < 0)
++              return ret;
++      if (ret == 0)
++              return -ENODEV;
+-      return psy->desc->set_property(psy,
+-                              POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
++      return 0;
+ }
+-EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier);
++EXPORT_SYMBOL_GPL(power_supply_get_property_from_supplier);
+ int power_supply_set_battery_charged(struct power_supply *psy)
+ {
+diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
+index 9ca1f120a2117..0735b8963e0af 100644
+--- a/include/linux/power_supply.h
++++ b/include/linux/power_supply.h
+@@ -420,8 +420,9 @@ power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table
+                               int table_len, int temp);
+ extern void power_supply_changed(struct power_supply *psy);
+ extern int power_supply_am_i_supplied(struct power_supply *psy);
+-extern int power_supply_set_input_current_limit_from_supplier(
+-                                       struct power_supply *psy);
++int power_supply_get_property_from_supplier(struct power_supply *psy,
++                                          enum power_supply_property psp,
++                                          union power_supply_propval *val);
+ extern int power_supply_set_battery_charged(struct power_supply *psy);
+ #ifdef CONFIG_POWER_SUPPLY
+-- 
+2.39.2
+
index e44f0a7d2350986b6b40da2b81b97a2614476675..91dda97824d38d4ee1352d6a4c88d0b8a64c6d21 100644 (file)
@@ -67,3 +67,16 @@ firmware-arm_ffa-set-reserved-mbz-fields-to-zero-in-the-memory-descriptors.patch
 regulator-mt6359-add-read-check-for-pmic-mt6359.patch
 3c589_cs-fix-an-error-handling-path-in-tc589_probe.patch
 net-phy-mscc-add-vsc8502-to-module_device_table.patch
+power-supply-bq27xxx-expose-battery-data-when-ci-1.patch
+power-supply-bq27xxx-move-bq27xxx_battery_update-dow.patch
+power-supply-bq27xxx-ensure-power_supply_changed-is-.patch
+power-supply-bq27xxx-after-charger-plug-in-out-wait-.patch
+power-supply-core-refactor-power_supply_set_input_cu.patch
+power-supply-bq24190-call-power_supply_changed-after.patch
+bpf-fix-a-memory-leak-in-the-lru-and-lru_percpu-hash.patch
+net-mlx5-devcom-only-supports-2-ports.patch
+net-mlx5e-fix-deadlock-in-tc-route-query-code.patch
+net-mlx5-devcom-serialize-devcom-registration.patch
+platform-x86-isst-punit-device-mapping-with-sub-numa.patch
+platform-x86-isst-remove-8-socket-limit.patch
+net-phy-mscc-enable-vsc8501-2-rgmii-rx-clock.patch