From 8e76741c3d8b20dfa2d6c30fa10ff927cfd93d82 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 28 Mar 2022 11:26:08 -0500 Subject: ipmi: Add a limit on the number of users that may use IPMI Each user uses memory, we need limits to avoid a rogue program from running the system out of memory. Based on work by Chen Guanqiao Cc: Chen Guanqiao Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index f1827257ef0e..649bb270c43b 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -145,6 +145,12 @@ module_param(default_max_retries, uint, 0644); MODULE_PARM_DESC(default_max_retries, "The time (milliseconds) between retry sends in maintenance mode"); +/* The default maximum number of users that may register. */ +static unsigned int max_users = 30; +module_param(max_users, uint, 0644); +MODULE_PARM_DESC(max_users, + "The most users that may use the IPMI stack at one time."); + /* Call every ~1000 ms. */ #define IPMI_TIMEOUT_TIME 1000 @@ -442,6 +448,7 @@ struct ipmi_smi { */ struct list_head users; struct srcu_struct users_srcu; + atomic_t nr_users; /* Used for wake ups at startup. */ wait_queue_head_t waitq; @@ -1230,6 +1237,11 @@ int ipmi_create_user(unsigned int if_num, goto out_kfree; found: + if (atomic_add_return(1, &intf->nr_users) > max_users) { + rv = -EBUSY; + goto out_kfree; + } + INIT_WORK(&new_user->remove_work, free_user_work); rv = init_srcu_struct(&new_user->release_barrier); @@ -1262,6 +1274,7 @@ int ipmi_create_user(unsigned int if_num, return 0; out_kfree: + atomic_dec(&intf->nr_users); srcu_read_unlock(&ipmi_interfaces_srcu, index); vfree(new_user); return rv; @@ -1336,6 +1349,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user) /* Remove the user from the interface's sequence table. */ spin_lock_irqsave(&intf->seq_lock, flags); list_del_rcu(&user->link); + atomic_dec(&intf->nr_users); for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { if (intf->seq_table[i].inuse @@ -3529,6 +3543,7 @@ int ipmi_add_smi(struct module *owner, if (slave_addr != 0) intf->addrinfo[0].address = slave_addr; INIT_LIST_HEAD(&intf->users); + atomic_set(&intf->nr_users, 0); intf->handlers = handlers; intf->send_info = send_info; spin_lock_init(&intf->seq_lock); -- cgit v1.2.3 From 333730e456fa67eaf6032c6371936fd4aca6cc62 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 28 Mar 2022 11:39:29 -0500 Subject: ipmi: Limit the number of message a user may have outstanding This way a rogue application can't use up a bunch of memory. Based on work by Chen Guanqiao Cc: Chen Guanqiao Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 649bb270c43b..65a9e2629af1 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -151,6 +151,12 @@ module_param(max_users, uint, 0644); MODULE_PARM_DESC(max_users, "The most users that may use the IPMI stack at one time."); +/* The default maximum number of message a user may have outstanding. */ +static unsigned int max_msgs_per_user = 100; +module_param(max_msgs_per_user, uint, 0644); +MODULE_PARM_DESC(max_msgs_per_user, + "The most message a user may have outstanding."); + /* Call every ~1000 ms. */ #define IPMI_TIMEOUT_TIME 1000 @@ -193,6 +199,8 @@ struct ipmi_user { /* Does this interface receive IPMI events? */ bool gets_events; + atomic_t nr_msgs; + /* Free must run in process context for RCU cleanup. */ struct work_struct remove_work; }; @@ -934,11 +942,13 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg) * risk. At this moment, simply skip it in that case. */ ipmi_free_recv_msg(msg); + atomic_dec(&msg->user->nr_msgs); } else { int index; struct ipmi_user *user = acquire_ipmi_user(msg->user, &index); if (user) { + atomic_dec(&user->nr_msgs); user->handler->ipmi_recv_hndl(msg, user->handler_data); release_ipmi_user(user, index); } else { @@ -1256,6 +1266,7 @@ int ipmi_create_user(unsigned int if_num, /* Note that each existing user holds a refcount to the interface. */ kref_get(&intf->refcount); + atomic_set(&new_user->nr_msgs, 0); kref_init(&new_user->refcount); new_user->handler = handler; new_user->handler_data = handler_data; @@ -2298,6 +2309,14 @@ static int i_ipmi_request(struct ipmi_user *user, struct ipmi_recv_msg *recv_msg; int rv = 0; + if (user) { + if (atomic_add_return(1, &user->nr_msgs) > max_msgs_per_user) { + /* Decrement will happen at the end of the routine. */ + rv = -EBUSY; + goto out; + } + } + if (supplied_recv) recv_msg = supplied_recv; else { @@ -2369,6 +2388,8 @@ out_err: rcu_read_unlock(); out: + if (rv && user) + atomic_dec(&user->nr_msgs); return rv; } -- cgit v1.2.3 From f60231885fa986fcd5503f4eb9ef3e53a2002b12 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 29 Mar 2022 08:31:36 -0500 Subject: ipmi: Add a sysfs interface to view the number of users A count of users is kept for each interface, allow it to be viewed. Based on work by Chen Guanqiao Cc: Chen Guanqiao Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 65a9e2629af1..8b5d39793997 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -457,6 +457,8 @@ struct ipmi_smi { struct list_head users; struct srcu_struct users_srcu; atomic_t nr_users; + struct device_attribute nr_users_devattr; + /* Used for wake ups at startup. */ wait_queue_head_t waitq; @@ -3506,6 +3508,17 @@ void ipmi_poll_interface(struct ipmi_user *user) } EXPORT_SYMBOL(ipmi_poll_interface); +static ssize_t nr_users_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ipmi_smi *intf = container_of(attr, + struct ipmi_smi, nr_users_devattr); + + return sysfs_emit(buf, "%d\n", atomic_read(&intf->nr_users)); +} +static DEVICE_ATTR_RO(nr_users); + static void redo_bmc_reg(struct work_struct *work) { struct ipmi_smi *intf = container_of(work, struct ipmi_smi, @@ -3628,6 +3641,12 @@ int ipmi_add_smi(struct module *owner, if (rv) goto out_err_bmc_reg; + intf->nr_users_devattr = dev_attr_nr_users; + sysfs_attr_init(&intf->nr_users_devattr.attr); + rv = device_create_file(intf->si_dev, &intf->nr_users_devattr); + if (rv) + goto out_err_bmc_reg; + /* * Keep memory order straight for RCU readers. Make * sure everything else is committed to memory before @@ -3727,6 +3746,8 @@ void ipmi_unregister_smi(struct ipmi_smi *intf) /* At this point no users can be added to the interface. */ + device_remove_file(intf->si_dev, &intf->nr_users_devattr); + /* * Call all the watcher interfaces to tell them that * an interface is going away. -- cgit v1.2.3 From d5d91586beda89b204dd1956a27e3ed2309ea995 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 29 Mar 2022 13:13:34 -0500 Subject: ipmi: Add a sysfs count of total outstanding messages for an interface Go through each user and add its message count to a total and print the total. It would be nice to have a per-user file, but there's no user sysfs entity at this point to hang it off of. Probably not worth the effort. Based on work by Chen Guanqiao Cc: Chen Guanqiao Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8b5d39793997..5d033fadba6a 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -458,6 +458,7 @@ struct ipmi_smi { struct srcu_struct users_srcu; atomic_t nr_users; struct device_attribute nr_users_devattr; + struct device_attribute nr_msgs_devattr; /* Used for wake ups at startup. */ @@ -3519,6 +3520,25 @@ static ssize_t nr_users_show(struct device *dev, } static DEVICE_ATTR_RO(nr_users); +static ssize_t nr_msgs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ipmi_smi *intf = container_of(attr, + struct ipmi_smi, nr_msgs_devattr); + struct ipmi_user *user; + int index; + unsigned int count = 0; + + index = srcu_read_lock(&intf->users_srcu); + list_for_each_entry_rcu(user, &intf->users, link) + count += atomic_read(&user->nr_msgs); + srcu_read_unlock(&intf->users_srcu, index); + + return sysfs_emit(buf, "%u\n", count); +} +static DEVICE_ATTR_RO(nr_msgs); + static void redo_bmc_reg(struct work_struct *work) { struct ipmi_smi *intf = container_of(work, struct ipmi_smi, @@ -3647,6 +3667,14 @@ int ipmi_add_smi(struct module *owner, if (rv) goto out_err_bmc_reg; + intf->nr_msgs_devattr = dev_attr_nr_msgs; + sysfs_attr_init(&intf->nr_msgs_devattr.attr); + rv = device_create_file(intf->si_dev, &intf->nr_msgs_devattr); + if (rv) { + device_remove_file(intf->si_dev, &intf->nr_users_devattr); + goto out_err_bmc_reg; + } + /* * Keep memory order straight for RCU readers. Make * sure everything else is committed to memory before @@ -3746,6 +3774,7 @@ void ipmi_unregister_smi(struct ipmi_smi *intf) /* At this point no users can be added to the interface. */ + device_remove_file(intf->si_dev, &intf->nr_msgs_devattr); device_remove_file(intf->si_dev, &intf->nr_users_devattr); /* -- cgit v1.2.3 From 0924c5a0cbed5831a2a0ff2f9a19692265f1ab92 Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Thu, 24 Mar 2022 18:11:59 +0100 Subject: ipmi: use simple i2c probe function The i2c probe functions here don't use the id information provided in their second argument, so the single-parameter i2c probe function ("probe_new") can be used instead. This avoids scanning the identifier tables during probes. Signed-off-by: Stephen Kitt Message-Id: <20220324171159.544565-1-steve@sk2.org> Signed-off-by: Corey Minyard Reviewed-by: Wolfram Sang --- drivers/char/ipmi/ipmb_dev_int.c | 5 ++--- drivers/char/ipmi/ipmi_ipmb.c | 5 ++--- drivers/char/ipmi/ipmi_ssif.c | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c index 49b8f22fdcf0..db40037eb347 100644 --- a/drivers/char/ipmi/ipmb_dev_int.c +++ b/drivers/char/ipmi/ipmb_dev_int.c @@ -299,8 +299,7 @@ static int ipmb_slave_cb(struct i2c_client *client, return 0; } -static int ipmb_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ipmb_probe(struct i2c_client *client) { struct ipmb_dev *ipmb_dev; int ret; @@ -369,7 +368,7 @@ static struct i2c_driver ipmb_driver = { .name = "ipmb-dev", .acpi_match_table = ACPI_PTR(acpi_ipmb_id), }, - .probe = ipmb_probe, + .probe_new = ipmb_probe, .remove = ipmb_remove, .id_table = ipmb_id, }; diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index b81b862532fb..7a83fbb4e379 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -442,8 +442,7 @@ static int ipmi_ipmb_remove(struct i2c_client *client) return 0; } -static int ipmi_ipmb_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ipmi_ipmb_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct ipmi_ipmb_dev *iidev; @@ -570,7 +569,7 @@ static struct i2c_driver ipmi_ipmb_driver = { .name = DEVICE_NAME, .of_match_table = of_ipmi_ipmb_match, }, - .probe = ipmi_ipmb_probe, + .probe_new = ipmi_ipmb_probe, .remove = ipmi_ipmb_remove, .id_table = ipmi_ipmb_id, }; diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index f199cc194844..0aff18942552 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -1619,7 +1619,7 @@ static int ssif_check_and_remove(struct i2c_client *client, return 0; } -static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int ssif_probe(struct i2c_client *client) { unsigned char msg[3]; unsigned char *resp; @@ -2037,7 +2037,7 @@ static struct i2c_driver ssif_i2c_driver = { .driver = { .name = DEVICE_NAME }, - .probe = ssif_probe, + .probe_new = ssif_probe, .remove = ssif_remove, .alert = ssif_alert, .id_table = ssif_id, -- cgit v1.2.3 From 7602b957e2404e5f98d9a40b68f1fd27f0028712 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 1 Apr 2022 07:44:53 -0500 Subject: ipmi:ssif: Check for NULL msg when handling events and messages Even though it's not possible to get into the SSIF_GETTING_MESSAGES and SSIF_GETTING_EVENTS states without a valid message in the msg field, it's probably best to be defensive here and check and print a log, since that means something else went wrong. Also add a default clause to that switch statement to release the lock and print a log, in case the state variable gets messed up somehow. Reported-by: Haowen Bai Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_ssif.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 0aff18942552..9ffc68dc2537 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -814,6 +814,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, break; case SSIF_GETTING_EVENTS: + if (!msg) { + /* Should never happen, but just in case. */ + dev_warn(&ssif_info->client->dev, + "No message set while getting events\n"); + ipmi_ssif_unlock_cond(ssif_info, flags); + break; + } + if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) { /* Error getting event, probably done. */ msg->done(msg); @@ -838,6 +846,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, break; case SSIF_GETTING_MESSAGES: + if (!msg) { + /* Should never happen, but just in case. */ + dev_warn(&ssif_info->client->dev, + "No message set while getting messages\n"); + ipmi_ssif_unlock_cond(ssif_info, flags); + break; + } + if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) { /* Error getting event, probably done. */ msg->done(msg); @@ -861,6 +877,13 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result, deliver_recv_msg(ssif_info, msg); } break; + + default: + /* Should never happen, but just in case. */ + dev_warn(&ssif_info->client->dev, + "Invalid state in message done handling: %d\n", + ssif_info->ssif_state); + ipmi_ssif_unlock_cond(ssif_info, flags); } flags = ipmi_ssif_lock_cond(ssif_info, &oflags); -- cgit v1.2.3 From 9824117dd964ecebf5d81990dbf21dfb56445049 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 12 Apr 2022 15:38:51 -0500 Subject: ipmi: Add an intializer for ipmi_smi_msg struct There was a "type" element added to this structure, but some static values were missed. The default value will be zero, which is correct, but create an initializer for the type and initialize the type properly in the initializer to avoid future issues. Reported-by: Joe Wiese Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_poweroff.c | 4 +--- drivers/char/ipmi/ipmi_watchdog.c | 14 +++++--------- include/linux/ipmi_smi.h | 6 ++++++ 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index bc3a18daf97a..62e71c46ac5f 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -94,9 +94,7 @@ static void dummy_recv_free(struct ipmi_recv_msg *msg) { atomic_dec(&dummy_count); } -static struct ipmi_smi_msg halt_smi_msg = { - .done = dummy_smi_free -}; +static struct ipmi_smi_msg halt_smi_msg = INIT_IPMI_SMI_MSG(dummy_smi_free); static struct ipmi_recv_msg halt_recv_msg = { .done = dummy_recv_free }; diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 0604abdd249a..4c1e9663ea47 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -354,9 +354,7 @@ static void msg_free_recv(struct ipmi_recv_msg *msg) complete(&msg_wait); } } -static struct ipmi_smi_msg smi_msg = { - .done = msg_free_smi -}; +static struct ipmi_smi_msg smi_msg = INIT_IPMI_SMI_MSG(msg_free_smi); static struct ipmi_recv_msg recv_msg = { .done = msg_free_recv }; @@ -475,9 +473,8 @@ static void panic_recv_free(struct ipmi_recv_msg *msg) atomic_dec(&panic_done_count); } -static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = { - .done = panic_smi_free -}; +static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = + INIT_IPMI_SMI_MSG(panic_smi_free); static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = { .done = panic_recv_free }; @@ -516,9 +513,8 @@ static void panic_halt_ipmi_heartbeat(void) atomic_sub(2, &panic_done_count); } -static struct ipmi_smi_msg panic_halt_smi_msg = { - .done = panic_smi_free -}; +static struct ipmi_smi_msg panic_halt_smi_msg = + INIT_IPMI_SMI_MSG(panic_smi_free); static struct ipmi_recv_msg panic_halt_recv_msg = { .done = panic_recv_free }; diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 9277d21c2690..5d69820d8b02 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -125,6 +125,12 @@ struct ipmi_smi_msg { void (*done)(struct ipmi_smi_msg *msg); }; +#define INIT_IPMI_SMI_MSG(done_handler) \ +{ \ + .done = done_handler, \ + .type = IPMI_SMI_MSG_TYPE_NORMAL \ +} + struct ipmi_smi_handlers { struct module *owner; -- cgit v1.2.3 From f214549d717310f795c20db9497db3938116399d Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 12 Apr 2022 15:49:47 -0500 Subject: ipmi: Add an intializer for ipmi_recv_msg struct Don't hand-initialize the struct here, create a macro to initialize it so new fields added don't get forgotten in places. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_poweroff.c | 4 +--- drivers/char/ipmi/ipmi_watchdog.c | 14 +++++--------- include/linux/ipmi.h | 5 +++++ 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 62e71c46ac5f..163ec9749e55 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -95,9 +95,7 @@ static void dummy_recv_free(struct ipmi_recv_msg *msg) atomic_dec(&dummy_count); } static struct ipmi_smi_msg halt_smi_msg = INIT_IPMI_SMI_MSG(dummy_smi_free); -static struct ipmi_recv_msg halt_recv_msg = { - .done = dummy_recv_free -}; +static struct ipmi_recv_msg halt_recv_msg = INIT_IPMI_RECV_MSG(dummy_recv_free); /* diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 4c1e9663ea47..5b4e677929ca 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -355,9 +355,7 @@ static void msg_free_recv(struct ipmi_recv_msg *msg) } } static struct ipmi_smi_msg smi_msg = INIT_IPMI_SMI_MSG(msg_free_smi); -static struct ipmi_recv_msg recv_msg = { - .done = msg_free_recv -}; +static struct ipmi_recv_msg recv_msg = INIT_IPMI_RECV_MSG(msg_free_recv); static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, struct ipmi_recv_msg *recv_msg, @@ -475,9 +473,8 @@ static void panic_recv_free(struct ipmi_recv_msg *msg) static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = INIT_IPMI_SMI_MSG(panic_smi_free); -static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = { - .done = panic_recv_free -}; +static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = + INIT_IPMI_RECV_MSG(panic_recv_free); static void panic_halt_ipmi_heartbeat(void) { @@ -515,9 +512,8 @@ static void panic_halt_ipmi_heartbeat(void) static struct ipmi_smi_msg panic_halt_smi_msg = INIT_IPMI_SMI_MSG(panic_smi_free); -static struct ipmi_recv_msg panic_halt_recv_msg = { - .done = panic_recv_free -}; +static struct ipmi_recv_msg panic_halt_recv_msg = + INIT_IPMI_RECV_MSG(panic_recv_free); /* * Special call, doesn't claim any locks. This is only to be called diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 163831a087ef..a1c9c0d48ebf 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -72,6 +72,11 @@ struct ipmi_recv_msg { unsigned char msg_data[IPMI_MAX_MSG_LENGTH]; }; +#define INIT_IPMI_RECV_MSG(done_handler) \ +{ \ + .done = done_handler \ +} + /* Allocate and free the receive message. */ void ipmi_free_recv_msg(struct ipmi_recv_msg *msg); -- cgit v1.2.3 From 2ebaf18a0b7fb764bba6c806af99fe868cee93de Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 15 Apr 2022 07:23:32 -0500 Subject: ipmi: Fix pr_fmt to avoid compilation issues The was it was wouldn't work in some situations, simplify it. What was there was unnecessary complexity. Reported-by: kernel test robot Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 5d033fadba6a..7c7f71e656bd 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -11,8 +11,8 @@ * Copyright 2002 MontaVista Software Inc. */ -#define pr_fmt(fmt) "%s" fmt, "IPMI message handler: " -#define dev_fmt pr_fmt +#define pr_fmt(fmt) "IPMI message handler: " fmt +#define dev_fmt(fmt) pr_fmt(fmt) #include #include -- cgit v1.2.3 From b2c6941a5cf4a644010c0c9ecb33750e1f7eaf31 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 13 Apr 2022 17:40:54 -0500 Subject: ipmi: Convert pr_debug() to dev_dbg() A device is available at all debug points, use the right interface. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 7c7f71e656bd..35ba110dc378 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2384,7 +2384,8 @@ out_err: ipmi_free_smi_msg(smi_msg); ipmi_free_recv_msg(recv_msg); } else { - pr_debug("Send: %*ph\n", smi_msg->data_size, smi_msg->data); + dev_dbg(intf->si_dev, "Send: %*ph\n", + smi_msg->data_size, smi_msg->data); smi_send(intf, intf->handlers, smi_msg, priority); } @@ -3925,7 +3926,8 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf, msg->data[10] = ipmb_checksum(&msg->data[6], 4); msg->data_size = 11; - pr_debug("Invalid command: %*ph\n", msg->data_size, msg->data); + dev_dbg(intf->si_dev, "Invalid command: %*ph\n", + msg->data_size, msg->data); rcu_read_lock(); if (!intf->in_shutdown) { @@ -4533,7 +4535,7 @@ static int handle_one_recv_msg(struct ipmi_smi *intf, unsigned char cc; bool is_cmd = !((msg->rsp[0] >> 2) & 1); - pr_debug("Recv: %*ph\n", msg->rsp_size, msg->rsp); + dev_dbg(intf->si_dev, "Recv: %*ph\n", msg->rsp_size, msg->rsp); if (msg->rsp_size < 2) { /* Message is too small to be correct. */ @@ -4917,7 +4919,8 @@ smi_from_recv_msg(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg, smi_msg->data_size = recv_msg->msg.data_len; smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid); - pr_debug("Resend: %*ph\n", smi_msg->data_size, smi_msg->data); + dev_dbg(intf->si_dev, "Resend: %*ph\n", + smi_msg->data_size, smi_msg->data); return smi_msg; } -- cgit v1.2.3 From be8503597c3e20b1d1dfc68b3a8cb99ea4d261ba Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 13 Apr 2022 17:47:47 -0500 Subject: ipmi:si: Convert pr_debug() to dev_dbg() A device is available, use it. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_si_intf.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 5604a810fb3d..6e357ad76f2e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -264,15 +264,16 @@ static void cleanup_one_si(struct smi_info *smi_info); static void cleanup_ipmi_si(void); #ifdef DEBUG_TIMING -void debug_timestamp(char *msg) +void debug_timestamp(struct smi_info *smi_info, char *msg) { struct timespec64 t; ktime_get_ts64(&t); - pr_debug("**%s: %lld.%9.9ld\n", msg, t.tv_sec, t.tv_nsec); + dev_dbg(smi_info->io.dev, "**%s: %lld.%9.9ld\n", + msg, t.tv_sec, t.tv_nsec); } #else -#define debug_timestamp(x) +#define debug_timestamp(smi_info, x) #endif static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); @@ -318,7 +319,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) smi_info->curr_msg = smi_info->waiting_msg; smi_info->waiting_msg = NULL; - debug_timestamp("Start2"); + debug_timestamp(smi_info, "Start2"); err = atomic_notifier_call_chain(&xaction_notifier_list, 0, smi_info); if (err & NOTIFY_STOP_MASK) { @@ -538,7 +539,7 @@ static void handle_transaction_done(struct smi_info *smi_info) { struct ipmi_smi_msg *msg; - debug_timestamp("Done"); + debug_timestamp(smi_info, "Done"); switch (smi_info->si_state) { case SI_NORMAL: if (!smi_info->curr_msg) @@ -901,7 +902,7 @@ static void sender(void *send_info, struct smi_info *smi_info = send_info; unsigned long flags; - debug_timestamp("Enqueue"); + debug_timestamp(smi_info, "Enqueue"); if (smi_info->run_to_completion) { /* @@ -1079,7 +1080,7 @@ static void smi_timeout(struct timer_list *t) long timeout; spin_lock_irqsave(&(smi_info->si_lock), flags); - debug_timestamp("Timer"); + debug_timestamp(smi_info, "Timer"); jiffies_now = jiffies; time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies) @@ -1128,7 +1129,7 @@ irqreturn_t ipmi_si_irq_handler(int irq, void *data) smi_inc_stat(smi_info, interrupts); - debug_timestamp("Interrupt"); + debug_timestamp(smi_info, "Interrupt"); smi_event_handler(smi_info, 0); spin_unlock_irqrestore(&(smi_info->si_lock), flags); -- cgit v1.2.3 From 1016daf218371b4bb7300245d43060e511b60814 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Thu, 14 Apr 2022 11:07:05 -0500 Subject: ipmi: Make two logs unique There were two identical logs in two different places, so you couldn't tell which one was being logged. Make them unique. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 35ba110dc378..051839ec8763 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -4083,7 +4083,7 @@ static int handle_ipmb_direct_rcv_rsp(struct ipmi_smi *intf, recv_msg = (struct ipmi_recv_msg *) msg->user_data; if (recv_msg == NULL) { dev_warn(intf->si_dev, - "IPMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); + "IPMI direct message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); return 0; } @@ -4501,7 +4501,7 @@ static int handle_bmc_rsp(struct ipmi_smi *intf, recv_msg = (struct ipmi_recv_msg *) msg->user_data; if (recv_msg == NULL) { dev_warn(intf->si_dev, - "IPMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); + "IPMI SMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); return 0; } -- cgit v1.2.3 From 5396ccbd79ab03bd588bcfaa59f58c9bbf9fdcde Mon Sep 17 00:00:00 2001 From: Yu Zhe Date: Thu, 21 Apr 2022 08:09:41 -0700 Subject: ipmi: remove unnecessary type castings remove unnecessary void* type castings. Signed-off-by: Yu Zhe Message-Id: <20220421150941.7659-1-yuzhe@nfschina.com> Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_msghandler.c | 6 +++--- drivers/char/ipmi/ipmi_ssif.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 051839ec8763..703433493c85 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2332,7 +2332,7 @@ static int i_ipmi_request(struct ipmi_user *user, recv_msg->user_msg_data = user_msg_data; if (supplied_smi) - smi_msg = (struct ipmi_smi_msg *) supplied_smi; + smi_msg = supplied_smi; else { smi_msg = ipmi_alloc_smi_msg(); if (smi_msg == NULL) { @@ -4080,7 +4080,7 @@ static int handle_ipmb_direct_rcv_rsp(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg; struct ipmi_ipmb_direct_addr *daddr; - recv_msg = (struct ipmi_recv_msg *) msg->user_data; + recv_msg = msg->user_data; if (recv_msg == NULL) { dev_warn(intf->si_dev, "IPMI direct message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); @@ -4498,7 +4498,7 @@ static int handle_bmc_rsp(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg; struct ipmi_system_interface_addr *smi_addr; - recv_msg = (struct ipmi_recv_msg *) msg->user_data; + recv_msg = msg->user_data; if (recv_msg == NULL) { dev_warn(intf->si_dev, "IPMI SMI message received with no owner. This could be because of a malformed message, or because of a hardware error. Contact your hardware vendor for assistance.\n"); diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 9ffc68dc2537..fc742ee9c046 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -1076,7 +1076,7 @@ static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags) static void sender(void *send_info, struct ipmi_smi_msg *msg) { - struct ssif_info *ssif_info = (struct ssif_info *) send_info; + struct ssif_info *ssif_info = send_info; unsigned long oflags, *flags; BUG_ON(ssif_info->waiting_msg); @@ -1113,7 +1113,7 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data) */ static void request_events(void *send_info) { - struct ssif_info *ssif_info = (struct ssif_info *) send_info; + struct ssif_info *ssif_info = send_info; unsigned long oflags, *flags; if (!ssif_info->has_event_buffer) @@ -1130,7 +1130,7 @@ static void request_events(void *send_info) */ static void ssif_set_need_watch(void *send_info, unsigned int watch_mask) { - struct ssif_info *ssif_info = (struct ssif_info *) send_info; + struct ssif_info *ssif_info = send_info; unsigned long oflags, *flags; long timeout = 0; -- cgit v1.2.3 From a508e33956b538e034ed5df619a73ec7c15bda72 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Thu, 12 May 2022 08:44:45 +0400 Subject: ipmi:ipmb: Fix refcount leak in ipmi_ipmb_probe of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when done. Add missing of_node_put() to avoid refcount leak. Fixes: 00d93611f002 ("ipmi:ipmb: Add the ability to have a separate slave and master device") Signed-off-by: Miaoqian Lin Message-Id: <20220512044445.3102-1-linmq006@gmail.com> Cc: stable@vger.kernel.org # v5.17+ Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_ipmb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/char') diff --git a/drivers/char/ipmi/ipmi_ipmb.c b/drivers/char/ipmi/ipmi_ipmb.c index 7a83fbb4e379..ab19b4b3317e 100644 --- a/drivers/char/ipmi/ipmi_ipmb.c +++ b/drivers/char/ipmi/ipmi_ipmb.c @@ -475,6 +475,7 @@ static int ipmi_ipmb_probe(struct i2c_client *client) slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0); if (slave_np) { slave_adap = of_get_i2c_adapter_by_node(slave_np); + of_node_put(slave_np); if (!slave_adap) { dev_notice(&client->dev, "Could not find slave adapter\n"); -- cgit v1.2.3