Merge git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-drm-fsl-dcu.git] / drivers / char / ipmi / ipmi_msghandler.c
index 53582b53da95c449a9cb730f1b93734793139c30..3aff5e99b674360bad4fa42407d70a9d594656e4 100644 (file)
@@ -406,13 +406,14 @@ static void clean_up_interface_data(ipmi_smi_t intf)
        free_smi_msg_list(&intf->waiting_msgs);
        free_recv_msg_list(&intf->waiting_events);
 
-       /* Wholesale remove all the entries from the list in the
-        * interface and wait for RCU to know that none are in use. */
+       /*
+        * Wholesale remove all the entries from the list in the
+        * interface and wait for RCU to know that none are in use.
+        */
        mutex_lock(&intf->cmd_rcvrs_mutex);
-       list_add_rcu(&list, &intf->cmd_rcvrs);
-       list_del_rcu(&intf->cmd_rcvrs);
+       INIT_LIST_HEAD(&list);
+       list_splice_init_rcu(&intf->cmd_rcvrs, &list, synchronize_rcu);
        mutex_unlock(&intf->cmd_rcvrs_mutex);
-       synchronize_rcu();
 
        list_for_each_entry_safe(rcvr, rcvr2, &list, link)
                kfree(rcvr);
@@ -451,7 +452,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
        mutex_lock(&ipmi_interfaces_mutex);
 
        /* Build a list of things to deliver. */
-       list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
+       list_for_each_entry(intf, &ipmi_interfaces, link) {
                if (intf->intf_num == -1)
                        continue;
                e = kmalloc(sizeof(*e), GFP_KERNEL);
@@ -1886,7 +1887,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
                kfree(entry);
                rv = -ENOMEM;
        } else {
-               file->nlink = 1;
                file->data = data;
                file->read_proc = read_proc;
                file->write_proc = write_proc;
@@ -2760,9 +2760,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                synchronize_rcu();
                kref_put(&intf->refcount, intf_free);
        } else {
-               /* After this point the interface is legal to use. */
+               /*
+                * Keep memory order straight for RCU readers.  Make
+                * sure everything else is committed to memory before
+                * setting intf_num to mark the interface valid.
+                */
+               smp_wmb();
                intf->intf_num = i;
                mutex_unlock(&ipmi_interfaces_mutex);
+               /* After this point the interface is legal to use. */
                call_smi_watchers(i, intf->si_dev);
                mutex_unlock(&smi_watchers_mutex);
        }
@@ -3923,6 +3929,14 @@ static void send_panic_events(char *str)
                        /* Interface was not ready yet. */
                        continue;
 
+               /*
+                * intf_num is used as an marker to tell if the
+                * interface is valid.  Thus we need a read barrier to
+                * make sure data fetched before checking intf_num
+                * won't be used.
+                */
+               smp_rmb();
+
                /* First job here is to figure out where to send the
                   OEM events.  There's no way in IPMI to send OEM
                   events using an event send command, so we have to