Skip to content

Commit b1b5bf1

Browse files
committed
Merge tag 'for-linus-4.19-1' of https://github.com/cminyard/linux-ipmi
Pull IPMI update from Corey Minyard: "Add limits on the number of users and messages, plus sysfs interfaces to control those limits. Other than that, little cleanups, use dev_xxx() insted of pr_xxx(), create initializers for structures, fix a refcount leak, etc" * tag 'for-linus-4.19-1' of https://github.com/cminyard/linux-ipmi: ipmi:ipmb: Fix refcount leak in ipmi_ipmb_probe ipmi: remove unnecessary type castings ipmi: Make two logs unique ipmi:si: Convert pr_debug() to dev_dbg() ipmi: Convert pr_debug() to dev_dbg() ipmi: Fix pr_fmt to avoid compilation issues ipmi: Add an intializer for ipmi_recv_msg struct ipmi: Add an intializer for ipmi_smi_msg struct ipmi:ssif: Check for NULL msg when handling events and messages ipmi: use simple i2c probe function ipmi: Add a sysfs count of total outstanding messages for an interface ipmi: Add a sysfs interface to view the number of users ipmi: Limit the number of message a user may have outstanding ipmi: Add a limit on the number of users that may use IPMI
2 parents d335371 + a508e33 commit b1b5bf1

9 files changed

Lines changed: 165 additions & 54 deletions

File tree

drivers/char/ipmi/ipmb_dev_int.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,7 @@ static int ipmb_slave_cb(struct i2c_client *client,
299299
return 0;
300300
}
301301

302-
static int ipmb_probe(struct i2c_client *client,
303-
const struct i2c_device_id *id)
302+
static int ipmb_probe(struct i2c_client *client)
304303
{
305304
struct ipmb_dev *ipmb_dev;
306305
int ret;
@@ -369,7 +368,7 @@ static struct i2c_driver ipmb_driver = {
369368
.name = "ipmb-dev",
370369
.acpi_match_table = ACPI_PTR(acpi_ipmb_id),
371370
},
372-
.probe = ipmb_probe,
371+
.probe_new = ipmb_probe,
373372
.remove = ipmb_remove,
374373
.id_table = ipmb_id,
375374
};

drivers/char/ipmi/ipmi_ipmb.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,7 @@ static int ipmi_ipmb_remove(struct i2c_client *client)
442442
return 0;
443443
}
444444

445-
static int ipmi_ipmb_probe(struct i2c_client *client,
446-
const struct i2c_device_id *id)
445+
static int ipmi_ipmb_probe(struct i2c_client *client)
447446
{
448447
struct device *dev = &client->dev;
449448
struct ipmi_ipmb_dev *iidev;
@@ -476,6 +475,7 @@ static int ipmi_ipmb_probe(struct i2c_client *client,
476475
slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0);
477476
if (slave_np) {
478477
slave_adap = of_get_i2c_adapter_by_node(slave_np);
478+
of_node_put(slave_np);
479479
if (!slave_adap) {
480480
dev_notice(&client->dev,
481481
"Could not find slave adapter\n");
@@ -570,7 +570,7 @@ static struct i2c_driver ipmi_ipmb_driver = {
570570
.name = DEVICE_NAME,
571571
.of_match_table = of_ipmi_ipmb_match,
572572
},
573-
.probe = ipmi_ipmb_probe,
573+
.probe_new = ipmi_ipmb_probe,
574574
.remove = ipmi_ipmb_remove,
575575
.id_table = ipmi_ipmb_id,
576576
};

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
* Copyright 2002 MontaVista Software Inc.
1212
*/
1313

14-
#define pr_fmt(fmt) "%s" fmt, "IPMI message handler: "
15-
#define dev_fmt pr_fmt
14+
#define pr_fmt(fmt) "IPMI message handler: " fmt
15+
#define dev_fmt(fmt) pr_fmt(fmt)
1616

1717
#include <linux/module.h>
1818
#include <linux/errno.h>
@@ -145,6 +145,18 @@ module_param(default_max_retries, uint, 0644);
145145
MODULE_PARM_DESC(default_max_retries,
146146
"The time (milliseconds) between retry sends in maintenance mode");
147147

148+
/* The default maximum number of users that may register. */
149+
static unsigned int max_users = 30;
150+
module_param(max_users, uint, 0644);
151+
MODULE_PARM_DESC(max_users,
152+
"The most users that may use the IPMI stack at one time.");
153+
154+
/* The default maximum number of message a user may have outstanding. */
155+
static unsigned int max_msgs_per_user = 100;
156+
module_param(max_msgs_per_user, uint, 0644);
157+
MODULE_PARM_DESC(max_msgs_per_user,
158+
"The most message a user may have outstanding.");
159+
148160
/* Call every ~1000 ms. */
149161
#define IPMI_TIMEOUT_TIME 1000
150162

@@ -187,6 +199,8 @@ struct ipmi_user {
187199
/* Does this interface receive IPMI events? */
188200
bool gets_events;
189201

202+
atomic_t nr_msgs;
203+
190204
/* Free must run in process context for RCU cleanup. */
191205
struct work_struct remove_work;
192206
};
@@ -442,6 +456,10 @@ struct ipmi_smi {
442456
*/
443457
struct list_head users;
444458
struct srcu_struct users_srcu;
459+
atomic_t nr_users;
460+
struct device_attribute nr_users_devattr;
461+
struct device_attribute nr_msgs_devattr;
462+
445463

446464
/* Used for wake ups at startup. */
447465
wait_queue_head_t waitq;
@@ -927,11 +945,13 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
927945
* risk. At this moment, simply skip it in that case.
928946
*/
929947
ipmi_free_recv_msg(msg);
948+
atomic_dec(&msg->user->nr_msgs);
930949
} else {
931950
int index;
932951
struct ipmi_user *user = acquire_ipmi_user(msg->user, &index);
933952

934953
if (user) {
954+
atomic_dec(&user->nr_msgs);
935955
user->handler->ipmi_recv_hndl(msg, user->handler_data);
936956
release_ipmi_user(user, index);
937957
} else {
@@ -1230,6 +1250,11 @@ int ipmi_create_user(unsigned int if_num,
12301250
goto out_kfree;
12311251

12321252
found:
1253+
if (atomic_add_return(1, &intf->nr_users) > max_users) {
1254+
rv = -EBUSY;
1255+
goto out_kfree;
1256+
}
1257+
12331258
INIT_WORK(&new_user->remove_work, free_user_work);
12341259

12351260
rv = init_srcu_struct(&new_user->release_barrier);
@@ -1244,6 +1269,7 @@ int ipmi_create_user(unsigned int if_num,
12441269
/* Note that each existing user holds a refcount to the interface. */
12451270
kref_get(&intf->refcount);
12461271

1272+
atomic_set(&new_user->nr_msgs, 0);
12471273
kref_init(&new_user->refcount);
12481274
new_user->handler = handler;
12491275
new_user->handler_data = handler_data;
@@ -1262,6 +1288,7 @@ int ipmi_create_user(unsigned int if_num,
12621288
return 0;
12631289

12641290
out_kfree:
1291+
atomic_dec(&intf->nr_users);
12651292
srcu_read_unlock(&ipmi_interfaces_srcu, index);
12661293
vfree(new_user);
12671294
return rv;
@@ -1336,6 +1363,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
13361363
/* Remove the user from the interface's sequence table. */
13371364
spin_lock_irqsave(&intf->seq_lock, flags);
13381365
list_del_rcu(&user->link);
1366+
atomic_dec(&intf->nr_users);
13391367

13401368
for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
13411369
if (intf->seq_table[i].inuse
@@ -2284,6 +2312,14 @@ static int i_ipmi_request(struct ipmi_user *user,
22842312
struct ipmi_recv_msg *recv_msg;
22852313
int rv = 0;
22862314

2315+
if (user) {
2316+
if (atomic_add_return(1, &user->nr_msgs) > max_msgs_per_user) {
2317+
/* Decrement will happen at the end of the routine. */
2318+
rv = -EBUSY;
2319+
goto out;
2320+
}
2321+
}
2322+
22872323
if (supplied_recv)
22882324
recv_msg = supplied_recv;
22892325
else {
@@ -2296,7 +2332,7 @@ static int i_ipmi_request(struct ipmi_user *user,
22962332
recv_msg->user_msg_data = user_msg_data;
22972333

22982334
if (supplied_smi)
2299-
smi_msg = (struct ipmi_smi_msg *) supplied_smi;
2335+
smi_msg = supplied_smi;
23002336
else {
23012337
smi_msg = ipmi_alloc_smi_msg();
23022338
if (smi_msg == NULL) {
@@ -2348,13 +2384,16 @@ static int i_ipmi_request(struct ipmi_user *user,
23482384
ipmi_free_smi_msg(smi_msg);
23492385
ipmi_free_recv_msg(recv_msg);
23502386
} else {
2351-
pr_debug("Send: %*ph\n", smi_msg->data_size, smi_msg->data);
2387+
dev_dbg(intf->si_dev, "Send: %*ph\n",
2388+
smi_msg->data_size, smi_msg->data);
23522389

23532390
smi_send(intf, intf->handlers, smi_msg, priority);
23542391
}
23552392
rcu_read_unlock();
23562393

23572394
out:
2395+
if (rv && user)
2396+
atomic_dec(&user->nr_msgs);
23582397
return rv;
23592398
}
23602399

@@ -3471,6 +3510,36 @@ void ipmi_poll_interface(struct ipmi_user *user)
34713510
}
34723511
EXPORT_SYMBOL(ipmi_poll_interface);
34733512

3513+
static ssize_t nr_users_show(struct device *dev,
3514+
struct device_attribute *attr,
3515+
char *buf)
3516+
{
3517+
struct ipmi_smi *intf = container_of(attr,
3518+
struct ipmi_smi, nr_users_devattr);
3519+
3520+
return sysfs_emit(buf, "%d\n", atomic_read(&intf->nr_users));
3521+
}
3522+
static DEVICE_ATTR_RO(nr_users);
3523+
3524+
static ssize_t nr_msgs_show(struct device *dev,
3525+
struct device_attribute *attr,
3526+
char *buf)
3527+
{
3528+
struct ipmi_smi *intf = container_of(attr,
3529+
struct ipmi_smi, nr_msgs_devattr);
3530+
struct ipmi_user *user;
3531+
int index;
3532+
unsigned int count = 0;
3533+
3534+
index = srcu_read_lock(&intf->users_srcu);
3535+
list_for_each_entry_rcu(user, &intf->users, link)
3536+
count += atomic_read(&user->nr_msgs);
3537+
srcu_read_unlock(&intf->users_srcu, index);
3538+
3539+
return sysfs_emit(buf, "%u\n", count);
3540+
}
3541+
static DEVICE_ATTR_RO(nr_msgs);
3542+
34743543
static void redo_bmc_reg(struct work_struct *work)
34753544
{
34763545
struct ipmi_smi *intf = container_of(work, struct ipmi_smi,
@@ -3529,6 +3598,7 @@ int ipmi_add_smi(struct module *owner,
35293598
if (slave_addr != 0)
35303599
intf->addrinfo[0].address = slave_addr;
35313600
INIT_LIST_HEAD(&intf->users);
3601+
atomic_set(&intf->nr_users, 0);
35323602
intf->handlers = handlers;
35333603
intf->send_info = send_info;
35343604
spin_lock_init(&intf->seq_lock);
@@ -3592,6 +3662,20 @@ int ipmi_add_smi(struct module *owner,
35923662
if (rv)
35933663
goto out_err_bmc_reg;
35943664

3665+
intf->nr_users_devattr = dev_attr_nr_users;
3666+
sysfs_attr_init(&intf->nr_users_devattr.attr);
3667+
rv = device_create_file(intf->si_dev, &intf->nr_users_devattr);
3668+
if (rv)
3669+
goto out_err_bmc_reg;
3670+
3671+
intf->nr_msgs_devattr = dev_attr_nr_msgs;
3672+
sysfs_attr_init(&intf->nr_msgs_devattr.attr);
3673+
rv = device_create_file(intf->si_dev, &intf->nr_msgs_devattr);
3674+
if (rv) {
3675+
device_remove_file(intf->si_dev, &intf->nr_users_devattr);
3676+
goto out_err_bmc_reg;
3677+
}
3678+
35953679
/*
35963680
* Keep memory order straight for RCU readers. Make
35973681
* sure everything else is committed to memory before
@@ -3691,6 +3775,9 @@ void ipmi_unregister_smi(struct ipmi_smi *intf)
36913775

36923776
/* At this point no users can be added to the interface. */
36933777

3778+
device_remove_file(intf->si_dev, &intf->nr_msgs_devattr);
3779+
device_remove_file(intf->si_dev, &intf->nr_users_devattr);
3780+
36943781
/*
36953782
* Call all the watcher interfaces to tell them that
36963783
* an interface is going away.
@@ -3839,7 +3926,8 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
38393926
msg->data[10] = ipmb_checksum(&msg->data[6], 4);
38403927
msg->data_size = 11;
38413928

3842-
pr_debug("Invalid command: %*ph\n", msg->data_size, msg->data);
3929+
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
3930+
msg->data_size, msg->data);
38433931

38443932
rcu_read_lock();
38453933
if (!intf->in_shutdown) {
@@ -3992,10 +4080,10 @@ static int handle_ipmb_direct_rcv_rsp(struct ipmi_smi *intf,
39924080
struct ipmi_recv_msg *recv_msg;
39934081
struct ipmi_ipmb_direct_addr *daddr;
39944082

3995-
recv_msg = (struct ipmi_recv_msg *) msg->user_data;
4083+
recv_msg = msg->user_data;
39964084
if (recv_msg == NULL) {
39974085
dev_warn(intf->si_dev,
3998-
"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");
4086+
"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");
39994087
return 0;
40004088
}
40014089

@@ -4410,10 +4498,10 @@ static int handle_bmc_rsp(struct ipmi_smi *intf,
44104498
struct ipmi_recv_msg *recv_msg;
44114499
struct ipmi_system_interface_addr *smi_addr;
44124500

4413-
recv_msg = (struct ipmi_recv_msg *) msg->user_data;
4501+
recv_msg = msg->user_data;
44144502
if (recv_msg == NULL) {
44154503
dev_warn(intf->si_dev,
4416-
"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");
4504+
"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");
44174505
return 0;
44184506
}
44194507

@@ -4447,7 +4535,7 @@ static int handle_one_recv_msg(struct ipmi_smi *intf,
44474535
unsigned char cc;
44484536
bool is_cmd = !((msg->rsp[0] >> 2) & 1);
44494537

4450-
pr_debug("Recv: %*ph\n", msg->rsp_size, msg->rsp);
4538+
dev_dbg(intf->si_dev, "Recv: %*ph\n", msg->rsp_size, msg->rsp);
44514539

44524540
if (msg->rsp_size < 2) {
44534541
/* Message is too small to be correct. */
@@ -4831,7 +4919,8 @@ smi_from_recv_msg(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg,
48314919
smi_msg->data_size = recv_msg->msg.data_len;
48324920
smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
48334921

4834-
pr_debug("Resend: %*ph\n", smi_msg->data_size, smi_msg->data);
4922+
dev_dbg(intf->si_dev, "Resend: %*ph\n",
4923+
smi_msg->data_size, smi_msg->data);
48354924

48364925
return smi_msg;
48374926
}

drivers/char/ipmi/ipmi_poweroff.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,8 @@ static void dummy_recv_free(struct ipmi_recv_msg *msg)
9494
{
9595
atomic_dec(&dummy_count);
9696
}
97-
static struct ipmi_smi_msg halt_smi_msg = {
98-
.done = dummy_smi_free
99-
};
100-
static struct ipmi_recv_msg halt_recv_msg = {
101-
.done = dummy_recv_free
102-
};
97+
static struct ipmi_smi_msg halt_smi_msg = INIT_IPMI_SMI_MSG(dummy_smi_free);
98+
static struct ipmi_recv_msg halt_recv_msg = INIT_IPMI_RECV_MSG(dummy_recv_free);
10399

104100

105101
/*

drivers/char/ipmi/ipmi_si_intf.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,16 @@ static void cleanup_one_si(struct smi_info *smi_info);
264264
static void cleanup_ipmi_si(void);
265265

266266
#ifdef DEBUG_TIMING
267-
void debug_timestamp(char *msg)
267+
void debug_timestamp(struct smi_info *smi_info, char *msg)
268268
{
269269
struct timespec64 t;
270270

271271
ktime_get_ts64(&t);
272-
pr_debug("**%s: %lld.%9.9ld\n", msg, t.tv_sec, t.tv_nsec);
272+
dev_dbg(smi_info->io.dev, "**%s: %lld.%9.9ld\n",
273+
msg, t.tv_sec, t.tv_nsec);
273274
}
274275
#else
275-
#define debug_timestamp(x)
276+
#define debug_timestamp(smi_info, x)
276277
#endif
277278

278279
static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
@@ -318,7 +319,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
318319

319320
smi_info->curr_msg = smi_info->waiting_msg;
320321
smi_info->waiting_msg = NULL;
321-
debug_timestamp("Start2");
322+
debug_timestamp(smi_info, "Start2");
322323
err = atomic_notifier_call_chain(&xaction_notifier_list,
323324
0, smi_info);
324325
if (err & NOTIFY_STOP_MASK) {
@@ -538,7 +539,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
538539
{
539540
struct ipmi_smi_msg *msg;
540541

541-
debug_timestamp("Done");
542+
debug_timestamp(smi_info, "Done");
542543
switch (smi_info->si_state) {
543544
case SI_NORMAL:
544545
if (!smi_info->curr_msg)
@@ -901,7 +902,7 @@ static void sender(void *send_info,
901902
struct smi_info *smi_info = send_info;
902903
unsigned long flags;
903904

904-
debug_timestamp("Enqueue");
905+
debug_timestamp(smi_info, "Enqueue");
905906

906907
if (smi_info->run_to_completion) {
907908
/*
@@ -1079,7 +1080,7 @@ static void smi_timeout(struct timer_list *t)
10791080
long timeout;
10801081

10811082
spin_lock_irqsave(&(smi_info->si_lock), flags);
1082-
debug_timestamp("Timer");
1083+
debug_timestamp(smi_info, "Timer");
10831084

10841085
jiffies_now = jiffies;
10851086
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)
11281129

11291130
smi_inc_stat(smi_info, interrupts);
11301131

1131-
debug_timestamp("Interrupt");
1132+
debug_timestamp(smi_info, "Interrupt");
11321133

11331134
smi_event_handler(smi_info, 0);
11341135
spin_unlock_irqrestore(&(smi_info->si_lock), flags);

0 commit comments

Comments
 (0)