|
|
@@ -62,7 +62,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data,
|
|
|
{ }
|
|
|
#endif
|
|
|
|
|
|
-static int initialized;
|
|
|
+static bool initialized;
|
|
|
+static bool drvregistered;
|
|
|
|
|
|
enum ipmi_panic_event_op {
|
|
|
IPMI_SEND_PANIC_EVENT_NONE,
|
|
|
@@ -612,7 +613,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
|
|
|
|
|
|
static LIST_HEAD(ipmi_interfaces);
|
|
|
static DEFINE_MUTEX(ipmi_interfaces_mutex);
|
|
|
-DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
|
|
|
+struct srcu_struct ipmi_interfaces_srcu;
|
|
|
|
|
|
/*
|
|
|
* List of watchers that want to know when smi's are added and deleted.
|
|
|
@@ -720,7 +721,15 @@ struct watcher_entry {
|
|
|
int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
|
|
|
{
|
|
|
struct ipmi_smi *intf;
|
|
|
- int index;
|
|
|
+ int index, rv;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Make sure the driver is actually initialized, this handles
|
|
|
+ * problems with initialization order.
|
|
|
+ */
|
|
|
+ rv = ipmi_init_msghandler();
|
|
|
+ if (rv)
|
|
|
+ return rv;
|
|
|
|
|
|
mutex_lock(&smi_watchers_mutex);
|
|
|
|
|
|
@@ -1076,7 +1085,7 @@ int ipmi_create_user(unsigned int if_num,
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
struct ipmi_user *new_user;
|
|
|
- int rv = 0, index;
|
|
|
+ int rv, index;
|
|
|
struct ipmi_smi *intf;
|
|
|
|
|
|
/*
|
|
|
@@ -1094,18 +1103,9 @@ int ipmi_create_user(unsigned int if_num,
|
|
|
* Make sure the driver is actually initialized, this handles
|
|
|
* problems with initialization order.
|
|
|
*/
|
|
|
- if (!initialized) {
|
|
|
- rv = ipmi_init_msghandler();
|
|
|
- if (rv)
|
|
|
- return rv;
|
|
|
-
|
|
|
- /*
|
|
|
- * The init code doesn't return an error if it was turned
|
|
|
- * off, but it won't initialize. Check that.
|
|
|
- */
|
|
|
- if (!initialized)
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
+ rv = ipmi_init_msghandler();
|
|
|
+ if (rv)
|
|
|
+ return rv;
|
|
|
|
|
|
new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
|
|
|
if (!new_user)
|
|
|
@@ -3304,17 +3304,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
|
|
|
* Make sure the driver is actually initialized, this handles
|
|
|
* problems with initialization order.
|
|
|
*/
|
|
|
- if (!initialized) {
|
|
|
- rv = ipmi_init_msghandler();
|
|
|
- if (rv)
|
|
|
- return rv;
|
|
|
- /*
|
|
|
- * The init code doesn't return an error if it was turned
|
|
|
- * off, but it won't initialize. Check that.
|
|
|
- */
|
|
|
- if (!initialized)
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
+ rv = ipmi_init_msghandler();
|
|
|
+ if (rv)
|
|
|
+ return rv;
|
|
|
|
|
|
intf = kzalloc(sizeof(*intf), GFP_KERNEL);
|
|
|
if (!intf)
|
|
|
@@ -5030,6 +5022,22 @@ static int panic_event(struct notifier_block *this,
|
|
|
return NOTIFY_DONE;
|
|
|
}
|
|
|
|
|
|
+/* Must be called with ipmi_interfaces_mutex held. */
|
|
|
+static int ipmi_register_driver(void)
|
|
|
+{
|
|
|
+ int rv;
|
|
|
+
|
|
|
+ if (drvregistered)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ rv = driver_register(&ipmidriver.driver);
|
|
|
+ if (rv)
|
|
|
+ pr_err("Could not register IPMI driver\n");
|
|
|
+ else
|
|
|
+ drvregistered = true;
|
|
|
+ return rv;
|
|
|
+}
|
|
|
+
|
|
|
static struct notifier_block panic_block = {
|
|
|
.notifier_call = panic_event,
|
|
|
.next = NULL,
|
|
|
@@ -5040,66 +5048,74 @@ static int ipmi_init_msghandler(void)
|
|
|
{
|
|
|
int rv;
|
|
|
|
|
|
+ mutex_lock(&ipmi_interfaces_mutex);
|
|
|
+ rv = ipmi_register_driver();
|
|
|
+ if (rv)
|
|
|
+ goto out;
|
|
|
if (initialized)
|
|
|
- return 0;
|
|
|
-
|
|
|
- rv = driver_register(&ipmidriver.driver);
|
|
|
- if (rv) {
|
|
|
- pr_err(PFX "Could not register IPMI driver\n");
|
|
|
- return rv;
|
|
|
- }
|
|
|
+ goto out;
|
|
|
|
|
|
- pr_info("ipmi message handler version " IPMI_DRIVER_VERSION "\n");
|
|
|
+ init_srcu_struct(&ipmi_interfaces_srcu);
|
|
|
|
|
|
timer_setup(&ipmi_timer, ipmi_timeout, 0);
|
|
|
mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
|
|
|
|
|
|
atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
|
|
|
|
|
|
- initialized = 1;
|
|
|
+ initialized = true;
|
|
|
|
|
|
- return 0;
|
|
|
+out:
|
|
|
+ mutex_unlock(&ipmi_interfaces_mutex);
|
|
|
+ return rv;
|
|
|
}
|
|
|
|
|
|
static int __init ipmi_init_msghandler_mod(void)
|
|
|
{
|
|
|
- ipmi_init_msghandler();
|
|
|
- return 0;
|
|
|
+ int rv;
|
|
|
+
|
|
|
+ pr_info("version " IPMI_DRIVER_VERSION "\n");
|
|
|
+
|
|
|
+ mutex_lock(&ipmi_interfaces_mutex);
|
|
|
+ rv = ipmi_register_driver();
|
|
|
+ mutex_unlock(&ipmi_interfaces_mutex);
|
|
|
+
|
|
|
+ return rv;
|
|
|
}
|
|
|
|
|
|
static void __exit cleanup_ipmi(void)
|
|
|
{
|
|
|
int count;
|
|
|
|
|
|
- if (!initialized)
|
|
|
- return;
|
|
|
-
|
|
|
- atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
|
|
|
-
|
|
|
- /*
|
|
|
- * This can't be called if any interfaces exist, so no worry
|
|
|
- * about shutting down the interfaces.
|
|
|
- */
|
|
|
-
|
|
|
- /*
|
|
|
- * Tell the timer to stop, then wait for it to stop. This
|
|
|
- * avoids problems with race conditions removing the timer
|
|
|
- * here.
|
|
|
- */
|
|
|
- atomic_inc(&stop_operation);
|
|
|
- del_timer_sync(&ipmi_timer);
|
|
|
-
|
|
|
- driver_unregister(&ipmidriver.driver);
|
|
|
+ if (initialized) {
|
|
|
+ atomic_notifier_chain_unregister(&panic_notifier_list,
|
|
|
+ &panic_block);
|
|
|
|
|
|
- initialized = 0;
|
|
|
+ /*
|
|
|
+ * This can't be called if any interfaces exist, so no worry
|
|
|
+ * about shutting down the interfaces.
|
|
|
+ */
|
|
|
|
|
|
- /* Check for buffer leaks. */
|
|
|
- count = atomic_read(&smi_msg_inuse_count);
|
|
|
- if (count != 0)
|
|
|
- pr_warn(PFX "SMI message count %d at exit\n", count);
|
|
|
- count = atomic_read(&recv_msg_inuse_count);
|
|
|
- if (count != 0)
|
|
|
- pr_warn(PFX "recv message count %d at exit\n", count);
|
|
|
+ /*
|
|
|
+ * Tell the timer to stop, then wait for it to stop. This
|
|
|
+ * avoids problems with race conditions removing the timer
|
|
|
+ * here.
|
|
|
+ */
|
|
|
+ atomic_inc(&stop_operation);
|
|
|
+ del_timer_sync(&ipmi_timer);
|
|
|
+
|
|
|
+ initialized = false;
|
|
|
+
|
|
|
+ /* Check for buffer leaks. */
|
|
|
+ count = atomic_read(&smi_msg_inuse_count);
|
|
|
+ if (count != 0)
|
|
|
+ pr_warn(PFX "SMI message count %d at exit\n", count);
|
|
|
+ count = atomic_read(&recv_msg_inuse_count);
|
|
|
+ if (count != 0)
|
|
|
+ pr_warn(PFX "recv message count %d at exit\n", count);
|
|
|
+ cleanup_srcu_struct(&ipmi_interfaces_srcu);
|
|
|
+ }
|
|
|
+ if (drvregistered)
|
|
|
+ driver_unregister(&ipmidriver.driver);
|
|
|
}
|
|
|
module_exit(cleanup_ipmi);
|
|
|
|