diff options
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 31 |
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. */ |