From 3702dd46990cc654a26e9d88e6f7e57bceb70843 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sat, 10 Feb 2007 01:45:45 -0800 Subject: [PATCH] --- yaml --- r: 47568 b: refs/heads/master c: 78ba2faf71c63990cba9997f18cf1d610e06e3f2 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/char/ipmi/ipmi_msghandler.c | 29 +++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index 929fb838d70f..63b89d9018a4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3678d62f028689abc8ac5693b254e48f605f94ba +refs/heads/master: 78ba2faf71c63990cba9997f18cf1d610e06e3f2 diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index 53582b53da95..230064ede08d 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -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); @@ -2760,9 +2761,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 +3930,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