Skip to content

Commit 913a89f

Browse files
committed
ipmi: Don't initialize anything in the core until something uses it
The IPMI driver was recently modified to use SRCU, but it turns out this uses a chunk of percpu memory, even if IPMI is never used. So modify thing to on initialize on the first use. There was already code to sort of handle this for handling init races, so piggy back on top of that, and simplify it in the process. Signed-off-by: Corey Minyard <[email protected]> Reported-by: Tejun Heo <[email protected]> Cc: Paul E. McKenney <[email protected]> Reviewed-by: Paul E. McKenney <[email protected]> Cc: [email protected] # 4.18
1 parent 77f8269 commit 913a89f

File tree

1 file changed

+80
-63
lines changed

1 file changed

+80
-63
lines changed

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 80 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data,
6363
{ }
6464
#endif
6565

66-
static int initialized;
66+
static bool initialized;
67+
static bool drvregistered;
6768

6869
enum ipmi_panic_event_op {
6970
IPMI_SEND_PANIC_EVENT_NONE,
@@ -613,7 +614,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
613614

614615
static LIST_HEAD(ipmi_interfaces);
615616
static DEFINE_MUTEX(ipmi_interfaces_mutex);
616-
DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
617+
struct srcu_struct ipmi_interfaces_srcu;
617618

618619
/*
619620
* List of watchers that want to know when smi's are added and deleted.
@@ -721,7 +722,15 @@ struct watcher_entry {
721722
int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
722723
{
723724
struct ipmi_smi *intf;
724-
int index;
725+
int index, rv;
726+
727+
/*
728+
* Make sure the driver is actually initialized, this handles
729+
* problems with initialization order.
730+
*/
731+
rv = ipmi_init_msghandler();
732+
if (rv)
733+
return rv;
725734

726735
mutex_lock(&smi_watchers_mutex);
727736

@@ -1077,7 +1086,7 @@ int ipmi_create_user(unsigned int if_num,
10771086
{
10781087
unsigned long flags;
10791088
struct ipmi_user *new_user;
1080-
int rv = 0, index;
1089+
int rv, index;
10811090
struct ipmi_smi *intf;
10821091

10831092
/*
@@ -1095,18 +1104,9 @@ int ipmi_create_user(unsigned int if_num,
10951104
* Make sure the driver is actually initialized, this handles
10961105
* problems with initialization order.
10971106
*/
1098-
if (!initialized) {
1099-
rv = ipmi_init_msghandler();
1100-
if (rv)
1101-
return rv;
1102-
1103-
/*
1104-
* The init code doesn't return an error if it was turned
1105-
* off, but it won't initialize. Check that.
1106-
*/
1107-
if (!initialized)
1108-
return -ENODEV;
1109-
}
1107+
rv = ipmi_init_msghandler();
1108+
if (rv)
1109+
return rv;
11101110

11111111
new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
11121112
if (!new_user)
@@ -3301,17 +3301,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
33013301
* Make sure the driver is actually initialized, this handles
33023302
* problems with initialization order.
33033303
*/
3304-
if (!initialized) {
3305-
rv = ipmi_init_msghandler();
3306-
if (rv)
3307-
return rv;
3308-
/*
3309-
* The init code doesn't return an error if it was turned
3310-
* off, but it won't initialize. Check that.
3311-
*/
3312-
if (!initialized)
3313-
return -ENODEV;
3314-
}
3304+
rv = ipmi_init_msghandler();
3305+
if (rv)
3306+
return rv;
33153307

33163308
intf = kzalloc(sizeof(*intf), GFP_KERNEL);
33173309
if (!intf)
@@ -5027,6 +5019,22 @@ static int panic_event(struct notifier_block *this,
50275019
return NOTIFY_DONE;
50285020
}
50295021

5022+
/* Must be called with ipmi_interfaces_mutex held. */
5023+
static int ipmi_register_driver(void)
5024+
{
5025+
int rv;
5026+
5027+
if (drvregistered)
5028+
return 0;
5029+
5030+
rv = driver_register(&ipmidriver.driver);
5031+
if (rv)
5032+
pr_err("Could not register IPMI driver\n");
5033+
else
5034+
drvregistered = true;
5035+
return rv;
5036+
}
5037+
50305038
static struct notifier_block panic_block = {
50315039
.notifier_call = panic_event,
50325040
.next = NULL,
@@ -5037,66 +5045,75 @@ static int ipmi_init_msghandler(void)
50375045
{
50385046
int rv;
50395047

5048+
mutex_lock(&ipmi_interfaces_mutex);
5049+
rv = ipmi_register_driver();
5050+
if (rv)
5051+
goto out;
50405052
if (initialized)
5041-
return 0;
5053+
goto out;
50425054

5043-
rv = driver_register(&ipmidriver.driver);
5044-
if (rv) {
5045-
pr_err("Could not register IPMI driver\n");
5046-
return rv;
5047-
}
5048-
5049-
pr_info("version " IPMI_DRIVER_VERSION "\n");
5055+
init_srcu_struct(&ipmi_interfaces_srcu);
50505056

50515057
timer_setup(&ipmi_timer, ipmi_timeout, 0);
50525058
mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
50535059

50545060
atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
50555061

5056-
initialized = 1;
5062+
initialized = true;
50575063

5058-
return 0;
5064+
out:
5065+
mutex_unlock(&ipmi_interfaces_mutex);
5066+
return rv;
50595067
}
50605068

50615069
static int __init ipmi_init_msghandler_mod(void)
50625070
{
5063-
ipmi_init_msghandler();
5064-
return 0;
5071+
int rv;
5072+
5073+
pr_info("version " IPMI_DRIVER_VERSION "\n");
5074+
5075+
mutex_lock(&ipmi_interfaces_mutex);
5076+
rv = ipmi_register_driver();
5077+
mutex_unlock(&ipmi_interfaces_mutex);
5078+
5079+
return rv;
50655080
}
50665081

50675082
static void __exit cleanup_ipmi(void)
50685083
{
50695084
int count;
50705085

5071-
if (!initialized)
5072-
return;
5073-
5074-
atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
5086+
if (initialized) {
5087+
atomic_notifier_chain_unregister(&panic_notifier_list,
5088+
&panic_block);
50755089

5076-
/*
5077-
* This can't be called if any interfaces exist, so no worry
5078-
* about shutting down the interfaces.
5079-
*/
5090+
/*
5091+
* This can't be called if any interfaces exist, so no worry
5092+
* about shutting down the interfaces.
5093+
*/
50805094

5081-
/*
5082-
* Tell the timer to stop, then wait for it to stop. This
5083-
* avoids problems with race conditions removing the timer
5084-
* here.
5085-
*/
5086-
atomic_inc(&stop_operation);
5087-
del_timer_sync(&ipmi_timer);
5095+
/*
5096+
* Tell the timer to stop, then wait for it to stop. This
5097+
* avoids problems with race conditions removing the timer
5098+
* here.
5099+
*/
5100+
atomic_inc(&stop_operation);
5101+
del_timer_sync(&ipmi_timer);
50885102

5089-
driver_unregister(&ipmidriver.driver);
5103+
initialized = false;
50905104

5091-
initialized = 0;
5105+
/* Check for buffer leaks. */
5106+
count = atomic_read(&smi_msg_inuse_count);
5107+
if (count != 0)
5108+
pr_warn("SMI message count %d at exit\n", count);
5109+
count = atomic_read(&recv_msg_inuse_count);
5110+
if (count != 0)
5111+
pr_warn("recv message count %d at exit\n", count);
50925112

5093-
/* Check for buffer leaks. */
5094-
count = atomic_read(&smi_msg_inuse_count);
5095-
if (count != 0)
5096-
pr_warn("SMI message count %d at exit\n", count);
5097-
count = atomic_read(&recv_msg_inuse_count);
5098-
if (count != 0)
5099-
pr_warn("recv message count %d at exit\n", count);
5113+
cleanup_srcu_struct(&ipmi_interfaces_srcu);
5114+
}
5115+
if (drvregistered)
5116+
driver_unregister(&ipmidriver.driver);
51005117
}
51015118
module_exit(cleanup_ipmi);
51025119

0 commit comments

Comments
 (0)