aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 320d7f035bf9..c1d06ba449b6 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -209,7 +209,7 @@ struct ipmi_smi
209 209
210 /* The list of command receivers that are registered for commands 210 /* The list of command receivers that are registered for commands
211 on this interface. */ 211 on this interface. */
212 spinlock_t cmd_rcvrs_lock; 212 struct semaphore cmd_rcvrs_lock;
213 struct list_head cmd_rcvrs; 213 struct list_head cmd_rcvrs;
214 214
215 /* Events that were queues because no one was there to receive 215 /* Events that were queues because no one was there to receive
@@ -345,7 +345,6 @@ static void clean_up_interface_data(ipmi_smi_t intf)
345{ 345{
346 int i; 346 int i;
347 struct cmd_rcvr *rcvr, *rcvr2; 347 struct cmd_rcvr *rcvr, *rcvr2;
348 unsigned long flags;
349 struct list_head list; 348 struct list_head list;
350 349
351 free_recv_msg_list(&intf->waiting_msgs); 350 free_recv_msg_list(&intf->waiting_msgs);
@@ -353,10 +352,10 @@ static void clean_up_interface_data(ipmi_smi_t intf)
353 352
354 /* Wholesale remove all the entries from the list in the 353 /* Wholesale remove all the entries from the list in the
355 * interface and wait for RCU to know that none are in use. */ 354 * interface and wait for RCU to know that none are in use. */
356 spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); 355 down(&intf->cmd_rcvrs_lock);
357 list_add_rcu(&list, &intf->cmd_rcvrs); 356 list_add_rcu(&list, &intf->cmd_rcvrs);
358 list_del_rcu(&intf->cmd_rcvrs); 357 list_del_rcu(&intf->cmd_rcvrs);
359 spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); 358 up(&intf->cmd_rcvrs_lock);
360 synchronize_rcu(); 359 synchronize_rcu();
361 360
362 list_for_each_entry_safe(rcvr, rcvr2, &list, link) 361 list_for_each_entry_safe(rcvr, rcvr2, &list, link)
@@ -812,7 +811,7 @@ int ipmi_destroy_user(ipmi_user_t user)
812 * since other things may be using it till we do 811 * since other things may be using it till we do
813 * synchronize_rcu()) then free everything in that list. 812 * synchronize_rcu()) then free everything in that list.
814 */ 813 */
815 spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); 814 down(&intf->cmd_rcvrs_lock);
816 list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { 815 list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {
817 rcvr = list_entry(entry1, struct cmd_rcvr, link); 816 rcvr = list_entry(entry1, struct cmd_rcvr, link);
818 if (rcvr->user == user) { 817 if (rcvr->user == user) {
@@ -821,7 +820,7 @@ int ipmi_destroy_user(ipmi_user_t user)
821 rcvrs = rcvr; 820 rcvrs = rcvr;
822 } 821 }
823 } 822 }
824 spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); 823 up(&intf->cmd_rcvrs_lock);
825 synchronize_rcu(); 824 synchronize_rcu();
826 while (rcvrs) { 825 while (rcvrs) {
827 rcvr = rcvrs; 826 rcvr = rcvrs;
@@ -950,7 +949,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
950 rcvr->netfn = netfn; 949 rcvr->netfn = netfn;
951 rcvr->user = user; 950 rcvr->user = user;
952 951
953 spin_lock_irq(&intf->cmd_rcvrs_lock); 952 down(&intf->cmd_rcvrs_lock);
954 /* Make sure the command/netfn is not already registered. */ 953 /* Make sure the command/netfn is not already registered. */
955 entry = find_cmd_rcvr(intf, netfn, cmd); 954 entry = find_cmd_rcvr(intf, netfn, cmd);
956 if (entry) { 955 if (entry) {
@@ -961,7 +960,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
961 list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); 960 list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
962 961
963 out_unlock: 962 out_unlock:
964 spin_unlock_irq(&intf->cmd_rcvrs_lock); 963 up(&intf->cmd_rcvrs_lock);
965 if (rv) 964 if (rv)
966 kfree(rcvr); 965 kfree(rcvr);
967 966
@@ -975,17 +974,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user,
975 ipmi_smi_t intf = user->intf; 974 ipmi_smi_t intf = user->intf;
976 struct cmd_rcvr *rcvr; 975 struct cmd_rcvr *rcvr;
977 976
978 spin_lock_irq(&intf->cmd_rcvrs_lock); 977 down(&intf->cmd_rcvrs_lock);
979 /* Make sure the command/netfn is not already registered. */ 978 /* Make sure the command/netfn is not already registered. */
980 rcvr = find_cmd_rcvr(intf, netfn, cmd); 979 rcvr = find_cmd_rcvr(intf, netfn, cmd);
981 if ((rcvr) && (rcvr->user == user)) { 980 if ((rcvr) && (rcvr->user == user)) {
982 list_del_rcu(&rcvr->link); 981 list_del_rcu(&rcvr->link);
983 spin_unlock_irq(&intf->cmd_rcvrs_lock); 982 up(&intf->cmd_rcvrs_lock);
984 synchronize_rcu(); 983 synchronize_rcu();
985 kfree(rcvr); 984 kfree(rcvr);
986 return 0; 985 return 0;
987 } else { 986 } else {
988 spin_unlock_irq(&intf->cmd_rcvrs_lock); 987 up(&intf->cmd_rcvrs_lock);
989 return -ENOENT; 988 return -ENOENT;
990 } 989 }
991} 990}
@@ -1858,7 +1857,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
1858 spin_lock_init(&intf->events_lock); 1857 spin_lock_init(&intf->events_lock);
1859 INIT_LIST_HEAD(&intf->waiting_events); 1858 INIT_LIST_HEAD(&intf->waiting_events);
1860 intf->waiting_events_count = 0; 1859 intf->waiting_events_count = 0;
1861 spin_lock_init(&intf->cmd_rcvrs_lock); 1860 init_MUTEX(&intf->cmd_rcvrs_lock);
1862 INIT_LIST_HEAD(&intf->cmd_rcvrs); 1861 INIT_LIST_HEAD(&intf->cmd_rcvrs);
1863 init_waitqueue_head(&intf->waitq); 1862 init_waitqueue_head(&intf->waitq);
1864 1863
@@ -2058,14 +2057,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
2058 netfn = msg->rsp[4] >> 2; 2057 netfn = msg->rsp[4] >> 2;
2059 cmd = msg->rsp[8]; 2058 cmd = msg->rsp[8];
2060 2059
2061 spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); 2060 rcu_read_lock();
2062 rcvr = find_cmd_rcvr(intf, netfn, cmd); 2061 rcvr = find_cmd_rcvr(intf, netfn, cmd);
2063 if (rcvr) { 2062 if (rcvr) {
2064 user = rcvr->user; 2063 user = rcvr->user;
2065 kref_get(&user->refcount); 2064 kref_get(&user->refcount);
2066 } else 2065 } else
2067 user = NULL; 2066 user = NULL;
2068 spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); 2067 rcu_read_unlock();
2069 2068
2070 if (user == NULL) { 2069 if (user == NULL) {
2071 /* We didn't find a user, deliver an error response. */ 2070 /* We didn't find a user, deliver an error response. */
@@ -2238,14 +2237,14 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
2238 netfn = msg->rsp[6] >> 2; 2237 netfn = msg->rsp[6] >> 2;
2239 cmd = msg->rsp[10]; 2238 cmd = msg->rsp[10];
2240 2239
2241 spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); 2240 rcu_read_lock();
2242 rcvr = find_cmd_rcvr(intf, netfn, cmd); 2241 rcvr = find_cmd_rcvr(intf, netfn, cmd);
2243 if (rcvr) { 2242 if (rcvr) {
2244 user = rcvr->user; 2243 user = rcvr->user;
2245 kref_get(&user->refcount); 2244 kref_get(&user->refcount);
2246 } else 2245 } else
2247 user = NULL; 2246 user = NULL;
2248 spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); 2247 rcu_read_unlock();
2249 2248
2250 if (user == NULL) { 2249 if (user == NULL) {
2251 /* We didn't find a user, just give up. */ 2250 /* We didn't find a user, just give up. */