aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_msghandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ipmi/ipmi_msghandler.c')
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 53582b53da95..3aff5e99b674 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -406,13 +406,14 @@ static void clean_up_interface_data(ipmi_smi_t intf)
406 free_smi_msg_list(&intf->waiting_msgs); 406 free_smi_msg_list(&intf->waiting_msgs);
407 free_recv_msg_list(&intf->waiting_events); 407 free_recv_msg_list(&intf->waiting_events);
408 408
409 /* Wholesale remove all the entries from the list in the 409 /*
410 * interface and wait for RCU to know that none are in use. */ 410 * Wholesale remove all the entries from the list in the
411 * interface and wait for RCU to know that none are in use.
412 */
411 mutex_lock(&intf->cmd_rcvrs_mutex); 413 mutex_lock(&intf->cmd_rcvrs_mutex);
412 list_add_rcu(&list, &intf->cmd_rcvrs); 414 INIT_LIST_HEAD(&list);
413 list_del_rcu(&intf->cmd_rcvrs); 415 list_splice_init_rcu(&intf->cmd_rcvrs, &list, synchronize_rcu);
414 mutex_unlock(&intf->cmd_rcvrs_mutex); 416 mutex_unlock(&intf->cmd_rcvrs_mutex);
415 synchronize_rcu();
416 417
417 list_for_each_entry_safe(rcvr, rcvr2, &list, link) 418 list_for_each_entry_safe(rcvr, rcvr2, &list, link)
418 kfree(rcvr); 419 kfree(rcvr);
@@ -451,7 +452,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
451 mutex_lock(&ipmi_interfaces_mutex); 452 mutex_lock(&ipmi_interfaces_mutex);
452 453
453 /* Build a list of things to deliver. */ 454 /* Build a list of things to deliver. */
454 list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { 455 list_for_each_entry(intf, &ipmi_interfaces, link) {
455 if (intf->intf_num == -1) 456 if (intf->intf_num == -1)
456 continue; 457 continue;
457 e = kmalloc(sizeof(*e), GFP_KERNEL); 458 e = kmalloc(sizeof(*e), GFP_KERNEL);
@@ -1886,7 +1887,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1886 kfree(entry); 1887 kfree(entry);
1887 rv = -ENOMEM; 1888 rv = -ENOMEM;
1888 } else { 1889 } else {
1889 file->nlink = 1;
1890 file->data = data; 1890 file->data = data;
1891 file->read_proc = read_proc; 1891 file->read_proc = read_proc;
1892 file->write_proc = write_proc; 1892 file->write_proc = write_proc;
@@ -2760,9 +2760,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
2760 synchronize_rcu(); 2760 synchronize_rcu();
2761 kref_put(&intf->refcount, intf_free); 2761 kref_put(&intf->refcount, intf_free);
2762 } else { 2762 } else {
2763 /* After this point the interface is legal to use. */ 2763 /*
2764 * Keep memory order straight for RCU readers. Make
2765 * sure everything else is committed to memory before
2766 * setting intf_num to mark the interface valid.
2767 */
2768 smp_wmb();
2764 intf->intf_num = i; 2769 intf->intf_num = i;
2765 mutex_unlock(&ipmi_interfaces_mutex); 2770 mutex_unlock(&ipmi_interfaces_mutex);
2771 /* After this point the interface is legal to use. */
2766 call_smi_watchers(i, intf->si_dev); 2772 call_smi_watchers(i, intf->si_dev);
2767 mutex_unlock(&smi_watchers_mutex); 2773 mutex_unlock(&smi_watchers_mutex);
2768 } 2774 }
@@ -3923,6 +3929,14 @@ static void send_panic_events(char *str)
3923 /* Interface was not ready yet. */ 3929 /* Interface was not ready yet. */
3924 continue; 3930 continue;
3925 3931
3932 /*
3933 * intf_num is used as an marker to tell if the
3934 * interface is valid. Thus we need a read barrier to
3935 * make sure data fetched before checking intf_num
3936 * won't be used.
3937 */
3938 smp_rmb();
3939
3926 /* First job here is to figure out where to send the 3940 /* First job here is to figure out where to send the
3927 OEM events. There's no way in IPMI to send OEM 3941 OEM events. There's no way in IPMI to send OEM
3928 events using an event send command, so we have to 3942 events using an event send command, so we have to