From cc37f43f26ea86e8f65f4002113def6e5820092e Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 28 May 2023 22:43:52 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...-leak-in-the-lru-and-lru_percpu-hash.patch | 68 ++++ ...et-mlx5-devcom-only-supports-2-ports.patch | 109 ++++++ ...devcom-serialize-devcom-registration.patch | 100 +++++ ...-fix-deadlock-in-tc-route-query-code.patch | 363 ++++++++++++++++++ ...mscc-enable-vsc8501-2-rgmii-rx-clock.patch | 134 +++++++ ...t-punit-device-mapping-with-sub-numa.patch | 150 ++++++++ ...tform-x86-isst-remove-8-socket-limit.patch | 70 ++++ ...4190-call-power_supply_changed-after.patch | 47 +++ ...7xxx-after-charger-plug-in-out-wait-.patch | 41 ++ ...7xxx-ensure-power_supply_changed-is-.patch | 98 +++++ ...q27xxx-expose-battery-data-when-ci-1.patch | 129 +++++++ ...7xxx-move-bq27xxx_battery_update-dow.patch | 168 ++++++++ ...e-refactor-power_supply_set_input_cu.patch | 171 +++++++++ queue-5.15/series | 13 + 14 files changed, 1661 insertions(+) create mode 100644 queue-5.15/bpf-fix-a-memory-leak-in-the-lru-and-lru_percpu-hash.patch create mode 100644 queue-5.15/net-mlx5-devcom-only-supports-2-ports.patch create mode 100644 queue-5.15/net-mlx5-devcom-serialize-devcom-registration.patch create mode 100644 queue-5.15/net-mlx5e-fix-deadlock-in-tc-route-query-code.patch create mode 100644 queue-5.15/net-phy-mscc-enable-vsc8501-2-rgmii-rx-clock.patch create mode 100644 queue-5.15/platform-x86-isst-punit-device-mapping-with-sub-numa.patch create mode 100644 queue-5.15/platform-x86-isst-remove-8-socket-limit.patch create mode 100644 queue-5.15/power-supply-bq24190-call-power_supply_changed-after.patch create mode 100644 queue-5.15/power-supply-bq27xxx-after-charger-plug-in-out-wait-.patch create mode 100644 queue-5.15/power-supply-bq27xxx-ensure-power_supply_changed-is-.patch create mode 100644 queue-5.15/power-supply-bq27xxx-expose-battery-data-when-ci-1.patch create mode 100644 queue-5.15/power-supply-bq27xxx-move-bq27xxx_battery_update-dow.patch create mode 100644 queue-5.15/power-supply-core-refactor-power_supply_set_input_cu.patch 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 index 00000000000..65f9551c283 --- /dev/null +++ b/queue-5.15/bpf-fix-a-memory-leak-in-the-lru-and-lru_percpu-hash.patch @@ -0,0 +1,68 @@ +From 7d3cab3c9ea91039c0cbfb88539e837a7b3ce8d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230522154558.2166815-1-aspsk@isovalent.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ebec66aaf04 --- /dev/null +++ b/queue-5.15/net-mlx5-devcom-only-supports-2-ports.patch @@ -0,0 +1,109 @@ +From 0f37bfd1d8a091aaa32eb5e028e9f86d68474dd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Feb 2022 12:23:34 +0000 +Subject: net/mlx5: devcom only supports 2 ports + +From: Mark Bloch + +[ 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 +Reviewed-by: Maor Gottlieb +Signed-off-by: Saeed Mahameed +Stable-dep-of: 691c041bf208 ("net/mlx5e: Fix deadlock in tc route query code") +Signed-off-by: Sasha Levin +--- + .../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 + ++#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 index 00000000000..2cbca9ae7d2 --- /dev/null +++ b/queue-5.15/net-mlx5-devcom-serialize-devcom-registration.patch @@ -0,0 +1,100 @@ +From c60ed581b95c9bc1797e88519e9f7279b3dd69a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 May 2023 13:36:42 +0300 +Subject: net/mlx5: Devcom, serialize devcom registration + +From: Shay Drory + +[ 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 +Reviewed-by: Mark Bloch +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + .../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 + #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 index 00000000000..0aa1d09c81a --- /dev/null +++ b/queue-5.15/net-mlx5e-fix-deadlock-in-tc-route-query-code.patch @@ -0,0 +1,363 @@ +From 4f7602f29c3d6d8024125b8ac5f6c0d0ed398285 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Mar 2023 14:20:51 +0200 +Subject: net/mlx5e: Fix deadlock in tc route query code + +From: Vlad Buslov + +[ 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] +[ 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 +Reviewed-by: Roi Dayan +Reviewed-by: Shay Drory +Reviewed-by: Tariq Toukan +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..7a2591c5c3b --- /dev/null +++ b/queue-5.15/net-phy-mscc-enable-vsc8501-2-rgmii-rx-clock.patch @@ -0,0 +1,134 @@ +From f43df598d867e5a7cad59723e565f87cb1acbc6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 May 2023 17:31:08 +0200 +Subject: net: phy: mscc: enable VSC8501/2 RGMII RX clock + +From: David Epping + +[ 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 +Reviewed-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a341fbc47dc --- /dev/null +++ b/queue-5.15/platform-x86-isst-punit-device-mapping-with-sub-numa.patch @@ -0,0 +1,150 @@ +From 32ce098fd779c25409930f618d9ba156d40095ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jun 2022 12:48:17 -0700 +Subject: platform/x86: ISST: PUNIT device mapping with Sub-NUMA clustering + +From: Srinivas Pandruvada + +[ 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 +Link: https://lore.kernel.org/r/20220629194817.2418240-1-srinivas.pandruvada@linux.intel.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Stable-dep-of: bbb320bfe2c3 ("platform/x86: ISST: Remove 8 socket limit") +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..f3c3f0a49fd --- /dev/null +++ b/queue-5.15/platform-x86-isst-remove-8-socket-limit.patch @@ -0,0 +1,70 @@ +From 1a4170641f45352e73fcd2fd4bdc7eb498fee8ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20230519160420.2588475-1-steve.wahl@hpe.com +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..67e34f15902 --- /dev/null +++ b/queue-5.15/power-supply-bq24190-call-power_supply_changed-after.patch @@ -0,0 +1,47 @@ +From 0e455263b8b1a134ef8b9e9b98501c20d37b85cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f84d91007eb --- /dev/null +++ b/queue-5.15/power-supply-bq27xxx-after-charger-plug-in-out-wait-.patch @@ -0,0 +1,41 @@ +From 07112bfee07128c0d44f8288dc37647d21dfcd0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4cb6b39e858 --- /dev/null +++ b/queue-5.15/power-supply-bq27xxx-ensure-power_supply_changed-is-.patch @@ -0,0 +1,98 @@ +From 35dfb547bb1a5458f9a9f6093b16890cb19ec9d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + 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 ++ + 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 index 00000000000..183ca708ff9 --- /dev/null +++ b/queue-5.15/power-supply-bq27xxx-expose-battery-data-when-ci-1.patch @@ -0,0 +1,129 @@ +From 4cd898f46dbc60506df9befb73d371e94b503d31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sicelo A. Mhlongo +Signed-off-by: Sebastian Reichel +Stable-dep-of: ff4c4a2a4437 ("power: supply: bq27xxx: Move bq27xxx_battery_update() down") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..30fec467289 --- /dev/null +++ b/queue-5.15/power-supply-bq27xxx-move-bq27xxx_battery_update-dow.patch @@ -0,0 +1,168 @@ +From e1b3d51e657e8b3004766b04e6a321cad3bd0f51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Apr 2023 20:23:36 +0200 +Subject: power: supply: bq27xxx: Move bq27xxx_battery_update() down + +From: Hans de Goede + +[ 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 +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c4fc4c2df51 --- /dev/null +++ b/queue-5.15/power-supply-core-refactor-power_supply_set_input_cu.patch @@ -0,0 +1,171 @@ +From c3156391121e1c14fd9da687c638ec0dc09b68c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Sebastian Reichel +Stable-dep-of: 77c2a3097d70 ("power: supply: bq24190: Call power_supply_changed() after updating input current") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index e44f0a7d235..91dda97824d 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 -- 2.47.3