| From b530f53c67137c330d4f585cd1e76174914ea912 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 16 Sep 2021 11:36:20 -0500 |
| Subject: ipmi: Disable some operations during a panic |
| |
| From: Corey Minyard <cminyard@mvista.com> |
| |
| [ Upstream commit b36eb5e7b75a756baa64909a176dd4269ee05a8b ] |
| |
| Don't do kfree or other risky things when oops_in_progress is set. |
| It's easy enough to avoid doing them |
| |
| Signed-off-by: Corey Minyard <cminyard@mvista.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/char/ipmi/ipmi_msghandler.c | 10 +++++++--- |
| drivers/char/ipmi/ipmi_watchdog.c | 17 ++++++++++++----- |
| 2 files changed, 19 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c |
| index ac656a6d5daf1..bd3c9fb029fa5 100644 |
| --- a/drivers/char/ipmi/ipmi_msghandler.c |
| +++ b/drivers/char/ipmi/ipmi_msghandler.c |
| @@ -4797,7 +4797,9 @@ static atomic_t recv_msg_inuse_count = ATOMIC_INIT(0); |
| static void free_smi_msg(struct ipmi_smi_msg *msg) |
| { |
| atomic_dec(&smi_msg_inuse_count); |
| - kfree(msg); |
| + /* Try to keep as much stuff out of the panic path as possible. */ |
| + if (!oops_in_progress) |
| + kfree(msg); |
| } |
| |
| struct ipmi_smi_msg *ipmi_alloc_smi_msg(void) |
| @@ -4816,7 +4818,9 @@ EXPORT_SYMBOL(ipmi_alloc_smi_msg); |
| static void free_recv_msg(struct ipmi_recv_msg *msg) |
| { |
| atomic_dec(&recv_msg_inuse_count); |
| - kfree(msg); |
| + /* Try to keep as much stuff out of the panic path as possible. */ |
| + if (!oops_in_progress) |
| + kfree(msg); |
| } |
| |
| static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) |
| @@ -4834,7 +4838,7 @@ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) |
| |
| void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) |
| { |
| - if (msg->user) |
| + if (msg->user && !oops_in_progress) |
| kref_put(&msg->user->refcount, free_user); |
| msg->done(msg); |
| } |
| diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c |
| index ae06e5402e9d5..72ad7fff64a7a 100644 |
| --- a/drivers/char/ipmi/ipmi_watchdog.c |
| +++ b/drivers/char/ipmi/ipmi_watchdog.c |
| @@ -337,13 +337,17 @@ static atomic_t msg_tofree = ATOMIC_INIT(0); |
| static DECLARE_COMPLETION(msg_wait); |
| static void msg_free_smi(struct ipmi_smi_msg *msg) |
| { |
| - if (atomic_dec_and_test(&msg_tofree)) |
| - complete(&msg_wait); |
| + if (atomic_dec_and_test(&msg_tofree)) { |
| + if (!oops_in_progress) |
| + complete(&msg_wait); |
| + } |
| } |
| static void msg_free_recv(struct ipmi_recv_msg *msg) |
| { |
| - if (atomic_dec_and_test(&msg_tofree)) |
| - complete(&msg_wait); |
| + if (atomic_dec_and_test(&msg_tofree)) { |
| + if (!oops_in_progress) |
| + complete(&msg_wait); |
| + } |
| } |
| static struct ipmi_smi_msg smi_msg = { |
| .done = msg_free_smi |
| @@ -429,8 +433,10 @@ static int _ipmi_set_timeout(int do_heartbeat) |
| rv = __ipmi_set_timeout(&smi_msg, |
| &recv_msg, |
| &send_heartbeat_now); |
| - if (rv) |
| + if (rv) { |
| + atomic_set(&msg_tofree, 0); |
| return rv; |
| + } |
| |
| wait_for_completion(&msg_wait); |
| |
| @@ -575,6 +581,7 @@ restart: |
| &recv_msg, |
| 1); |
| if (rv) { |
| + atomic_set(&msg_tofree, 0); |
| pr_warn("heartbeat send failure: %d\n", rv); |
| return rv; |
| } |
| -- |
| 2.33.0 |
| |