From d08048d4e03b68aeadce6100ba32a525b6e5ab3d Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 21 Apr 2026 08:40:21 -0500 Subject: [PATCH 1/9] ipmi:kcs: Reduce the number of retries The retry count was initially set to 10, which with the 5 second timeouts give 55 seconds to fail a message. The IPMI spec specifies the 5 second timeout, and it specifies retries for KCS but does not specify a number. 55 seconds is a long time, so reduce retries to 2. It matches the default in the BT state machine. This is 15 seconds, then, which is still a long time, but more reasonable. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_kcs_sm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index efda90dcf5b3..c89055db39e5 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -102,7 +102,7 @@ enum kcs_states { /* Timeouts in microseconds. */ #define IBF_RETRY_TIMEOUT (5*USEC_PER_SEC) #define OBF_RETRY_TIMEOUT (5*USEC_PER_SEC) -#define MAX_ERROR_RETRIES 10 +#define MAX_ERROR_RETRIES 2 #define ERROR0_OBF_WAIT_JIFFIES (2*HZ) struct si_sm_data { From cc3f0c66183022444c1ff35ad6885127200eb921 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 19 May 2026 13:57:22 +0800 Subject: [PATCH 2/9] ipmi: Use LIST_HEAD() to initialize on stack list head Use LIST_HEAD to initialize on stack list head. No intentional functional impact. Change generated with below coccinelle script: @@ identifier name; @@ - struct list_head name; + LIST_HEAD(name); ... when != name - INIT_LIST_HEAD(&name); Signed-off-by: Jisheng Zhang Message-ID: <20260519055722.13161-1-jszhang@kernel.org> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 869ac87a4b6a..7a4566046b68 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -1610,14 +1610,12 @@ int ipmi_set_gets_events(struct ipmi_user *user, bool val) { struct ipmi_smi *intf = user->intf; struct ipmi_recv_msg *msg, *msg2; - struct list_head msgs; + LIST_HEAD(msgs); user = acquire_ipmi_user(user); if (!user) return -ENODEV; - INIT_LIST_HEAD(&msgs); - mutex_lock(&intf->events_mutex); if (user->gets_events == val) goto out; @@ -3785,10 +3783,9 @@ static void cleanup_smi_msgs(struct ipmi_smi *intf) struct seq_table *ent; struct ipmi_smi_msg *msg; struct list_head *entry; - struct list_head tmplist; + LIST_HEAD(tmplist); /* Clear out our transmit queues and hold the messages. */ - INIT_LIST_HEAD(&tmplist); list_splice_tail(&intf->hp_xmit_msgs, &tmplist); list_splice_tail(&intf->xmit_msgs, &tmplist); @@ -4442,7 +4439,7 @@ static int handle_read_event_rsp(struct ipmi_smi *intf, struct ipmi_smi_msg *msg) { struct ipmi_recv_msg *recv_msg, *recv_msg2; - struct list_head msgs; + LIST_HEAD(msgs); struct ipmi_user *user; int rv = 0, deliver_count = 0; @@ -4457,8 +4454,6 @@ static int handle_read_event_rsp(struct ipmi_smi *intf, return 0; } - INIT_LIST_HEAD(&msgs); - mutex_lock(&intf->events_mutex); ipmi_inc_stat(intf, events); @@ -5101,7 +5096,7 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent, static bool ipmi_timeout_handler(struct ipmi_smi *intf, unsigned long timeout_period) { - struct list_head timeouts; + LIST_HEAD(timeouts); struct ipmi_recv_msg *msg, *msg2; unsigned long flags; int i; @@ -5120,7 +5115,6 @@ static bool ipmi_timeout_handler(struct ipmi_smi *intf, * have timed out, putting them in the timeouts * list. */ - INIT_LIST_HEAD(&timeouts); mutex_lock(&intf->seq_lock); if (intf->ipmb_maintenance_mode_timeout) { if (intf->ipmb_maintenance_mode_timeout <= timeout_period) From 8a8ba84886c905bd43dbdc3b3f78c7ba8f8661f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 19 May 2026 17:01:56 +0200 Subject: [PATCH 3/9] ipmi: Use named initializers for struct i2c_device_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition. This patch doesn't modify the compiled arrays, only their representation in source form benefits. The former was confirmed with x86 and arm64 builds. While touching these arrays, unify usage of whitespace in the list terminator. Signed-off-by: Uwe Kleine-König (The Capable Hub) Message-ID: <20260519150156.1590826-2-u.kleine-koenig@baylibre.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmb_dev_int.c | 4 ++-- drivers/char/ipmi/ipmi_ipmb.c | 4 ++-- drivers/char/ipmi/ipmi_ssif.c | 2 +- drivers/char/ipmi/ssif_bmc.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c index 2fe1d205ce4e..680ff15c30ab 100644 --- a/drivers/char/ipmi/ipmb_dev_int.c +++ b/drivers/char/ipmi/ipmb_dev_int.c @@ -353,8 +353,8 @@ static void ipmb_remove(struct i2c_client *client) } static const struct i2c_device_id ipmb_id[] = { - { "ipmb-dev" }, - {} + { .name = "ipmb-dev" }, + { } }; MODULE_DEVICE_TABLE(i2c, ipmb_id); diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index 28818952a7a4..1f1e5718f082 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -566,8 +566,8 @@ MODULE_DEVICE_TABLE(of, of_ipmi_ipmb_match); #endif static const struct i2c_device_id ipmi_ipmb_id[] = { - { DEVICE_NAME }, - {} + { .name = DEVICE_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, ipmi_ipmb_id); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index f419b46bf002..add043b812ea 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -2094,7 +2094,7 @@ static int dmi_ipmi_probe(struct platform_device *pdev) #endif static const struct i2c_device_id ssif_id[] = { - { DEVICE_NAME }, + { .name = DEVICE_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, ssif_id); diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c index 1df0e9284ad9..6036897725f3 100644 --- a/drivers/char/ipmi/ssif_bmc.c +++ b/drivers/char/ipmi/ssif_bmc.c @@ -874,7 +874,7 @@ static const struct of_device_id ssif_bmc_match[] = { MODULE_DEVICE_TABLE(of, ssif_bmc_match); static const struct i2c_device_id ssif_bmc_id[] = { - { DEVICE_NAME }, + { .name = DEVICE_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, ssif_bmc_id); From 6aa9e61c46465d231e9beddf56af7effd71be682 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 21 May 2026 14:06:27 +0100 Subject: [PATCH 4/9] ipmi: Fix user refcount underflow in event delivery ipmi_alloc_recv_msg(user) takes the temporary user reference owned by the receive message, and ipmi_free_recv_msg() drops it again. If event delivery fails after allocating receive messages for earlier users, handle_read_event_rsp() rolls those messages back with ipmi_free_recv_msg(). That rollback path still drops user->refcount explicitly after freeing each message. The extra put can free a user that remains linked on intf->users, so later event delivery may dereference a freed user or trip refcount_t's addition-on-zero warning when ipmi_alloc_recv_msg() tries to acquire another reference. Remove the stale explicit put and the now-dead user assignment. Keep the list_del() and ipmi_free_recv_msg() calls; they are the required rollback operations. Fixes: b52da4054ee0 ("ipmi: Rework user message limit handling") Cc: stable@vger.kernel.org # v6.18+ Signed-off-by: Matt Fleming Message-ID: <20260521130628.3641050-1-matt@readmodwrite.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 7a4566046b68..7ca2cacbaa05 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -4472,10 +4472,8 @@ static int handle_read_event_rsp(struct ipmi_smi *intf, mutex_unlock(&intf->users_mutex); list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { - user = recv_msg->user; list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); - kref_put(&user->refcount, free_ipmi_user); } /* * We couldn't allocate memory for the From 1aec36f2f362e4e6d25413113fc363c2c57a9aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Fri, 29 May 2026 13:03:39 +0200 Subject: [PATCH 5/9] ipmi:ssif: Drop unused assignment of platform_device_id driver data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver explicitly set the .driver_data member of struct platform_device_id to zero without relying on that value. Drop this unused assignments. While touching this array use a named initializer for assigning .name. Signed-off-by: Uwe Kleine-König (The Capable Hub) Message-ID: <5966a65daf432613a58af373af79c9c4421b3985.1780052427.git.u.kleine-koenig@baylibre.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_ssif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index add043b812ea..07f1d2327bb7 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -2127,7 +2127,7 @@ static void ssif_platform_remove(struct platform_device *dev) } static const struct platform_device_id ssif_plat_ids[] = { - { "dmi-ipmi-ssif", 0 }, + { .name = "dmi-ipmi-ssif" }, { } }; MODULE_DEVICE_TABLE(platform, ssif_plat_ids); From a3f3859cecacb64f18fd446271ece9a3b3f2d4de Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 3 Jun 2026 12:06:34 +0000 Subject: [PATCH 6/9] ipmi: fix refcount leak in i_ipmi_request() When a caller provides a `supplied_recv` message to i_ipmi_request(), the function increments the user's `nr_msgs` reference count. If an error occurs later, the out_err cleanup path only frees the recv_msg if the function allocated it itself (i.e., !supplied_recv). In the supplied_recv case the cleanup is skipped, leaving the reference count elevated. The caller ipmi_request_supply_msgs() does not release the supplied_recv on error, so the reference is permanently leaked. Fix this by explicitly reverting the reference count operations when a supplied recv_msg with a valid user pointer is present in the error path: decrement nr_msgs and drop the user's kref. Cc: stable@vger.kernel.org Fixes: b52da4054ee0 ("ipmi: Rework user message limit handling") Signed-off-by: Wentao Liang Message-ID: <20260603120634.3758747-1-vulab@iscas.ac.cn> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 7ca2cacbaa05..ab4c85f3d6fe 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2345,6 +2345,10 @@ static int i_ipmi_request(struct ipmi_user *user, if (smi_msg == NULL) { if (!supplied_recv) ipmi_free_recv_msg(recv_msg); + else if (recv_msg->user) { + atomic_dec(&recv_msg->user->nr_msgs); + kref_put(&recv_msg->user->refcount, free_ipmi_user); + } return -ENOMEM; } } @@ -2418,6 +2422,10 @@ static int i_ipmi_request(struct ipmi_user *user, ipmi_free_smi_msg(smi_msg); if (!supplied_recv) ipmi_free_recv_msg(recv_msg); + else if (recv_msg->user) { + atomic_dec(&recv_msg->user->nr_msgs); + kref_put(&recv_msg->user->refcount, free_ipmi_user); + } } return rv; } From 39851b7e580a65bee732e5364f0efb974b242370 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 3 Jun 2026 12:25:11 -0700 Subject: [PATCH 7/9] ipmi: si: Use platform_get_irq_optional() to retrieve interrupt Use platform_get_irq_optional() to retrieve the interrupt resource instead of directly parsing and mapping the OF node via irq_of_parse_and_map(). This is the standard pattern for platform devices. irq_of_parse_and_map() requires ire_dispose_mapping(), which is missing. Assisted-by: Antigravity:Gemini-3.5-Flash Signed-off-by: Rosen Penev Message-ID: <20260603192511.6869-1-rosenp@gmail.com> [Handle a negative return from platform_get_irq_optional() to mean no interrupt is assigned.] Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_si_platform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c index fb6e359ae494..704b06c919f0 100644 --- a/drivers/char/ipmi/ipmi_si_platform.c +++ b/drivers/char/ipmi/ipmi_si_platform.c @@ -276,7 +276,10 @@ static int of_ipmi_probe(struct platform_device *pdev) io.regspacing = regspacing ? be32_to_cpup(regspacing) : DEFAULT_REGSPACING; io.regshift = regshift ? be32_to_cpup(regshift) : 0; - io.irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + io.irq = platform_get_irq_optional(pdev, 0); + if (io.irq < 0) + io.irq = 0; + io.dev = &pdev->dev; dev_dbg(&pdev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n", From 9961c88b1cfb444ee03e9c1641cf170e9684c532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 16 Jun 2026 16:29:52 +0200 Subject: [PATCH 8/9] ipmi: Drop unused assignment of platform_device_id driver data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver explicitly sets the .driver_data member of struct platform_device_id to zero without relying on that value. Drop these unused assignments. Signed-off-by: Uwe Kleine-König (The Capable Hub) Message-ID: <9afdb7b0894f51fba78c64612428f7bb117901d1.1781620139.git.u.kleine-koenig@baylibre.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_si_platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c index 704b06c919f0..bdc481ce1302 100644 --- a/drivers/char/ipmi/ipmi_si_platform.c +++ b/drivers/char/ipmi/ipmi_si_platform.c @@ -436,9 +436,9 @@ void ipmi_remove_platform_device_by_name(char *name) } static const struct platform_device_id si_plat_ids[] = { - { "dmi-ipmi-si", 0 }, - { "hardcode-ipmi-si", 0 }, - { "hotmod-ipmi-si", 0 }, + { .name = "dmi-ipmi-si" }, + { .name = "hardcode-ipmi-si" }, + { .name = "hotmod-ipmi-si" }, { } }; From de9aa5ea2d9ea55234e78af1e6182979aa4f646a Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Sat, 20 Jun 2026 20:27:47 +0800 Subject: [PATCH 9/9] docs: ipmi: Fix path of the "hotmod" module parameter The correct path of the "hotmod" module parameter should be /sys/module/ipmi_si/parameters/hotmod. Fix it. Signed-off-by: Zenghui Yu Message-ID: <20260620122747.7902-1-zenghui.yu@linux.dev> Signed-off-by: Corey Minyard --- Documentation/driver-api/ipmi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-api/ipmi.rst b/Documentation/driver-api/ipmi.rst index f52ab2df2569..d08cee98e34a 100644 --- a/Documentation/driver-api/ipmi.rst +++ b/Documentation/driver-api/ipmi.rst @@ -495,7 +495,7 @@ tuned to the user's desired performance. The driver supports a hot add and remove of interfaces. This way, interfaces can be added or removed after the kernel is up and running. -This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a +This is done using /sys/module/ipmi_si/parameters/hotmod, which is a write-only parameter. You write a string to this interface. The string has the format::