mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 07:10:27 +00:00
[PATCH] IPMI: convert from semaphores to mutexes
Convert the remaining semaphores to mutexes in the IPMI driver. The watchdog was using a semaphore as a real semaphore (for IPC), so the conversion there required adding a completion. Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
8a3628d53f
commit
d6dfd1310d
@ -42,7 +42,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/devfs_fs_kernel.h>
|
||||
#include <linux/ipmi.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/compat.h>
|
||||
@ -55,7 +55,7 @@ struct ipmi_file_private
|
||||
struct file *file;
|
||||
struct fasync_struct *fasync_queue;
|
||||
wait_queue_head_t wait;
|
||||
struct semaphore recv_sem;
|
||||
struct mutex recv_mutex;
|
||||
int default_retries;
|
||||
unsigned int default_retry_time_ms;
|
||||
};
|
||||
@ -141,7 +141,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
|
||||
INIT_LIST_HEAD(&(priv->recv_msgs));
|
||||
init_waitqueue_head(&priv->wait);
|
||||
priv->fasync_queue = NULL;
|
||||
sema_init(&(priv->recv_sem), 1);
|
||||
mutex_init(&priv->recv_mutex);
|
||||
|
||||
/* Use the low-level defaults. */
|
||||
priv->default_retries = -1;
|
||||
@ -285,15 +285,15 @@ static int ipmi_ioctl(struct inode *inode,
|
||||
break;
|
||||
}
|
||||
|
||||
/* We claim a semaphore because we don't want two
|
||||
/* We claim a mutex because we don't want two
|
||||
users getting something from the queue at a time.
|
||||
Since we have to release the spinlock before we can
|
||||
copy the data to the user, it's possible another
|
||||
user will grab something from the queue, too. Then
|
||||
the messages might get out of order if something
|
||||
fails and the message gets put back onto the
|
||||
queue. This semaphore prevents that problem. */
|
||||
down(&(priv->recv_sem));
|
||||
queue. This mutex prevents that problem. */
|
||||
mutex_lock(&priv->recv_mutex);
|
||||
|
||||
/* Grab the message off the list. */
|
||||
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
|
||||
@ -352,7 +352,7 @@ static int ipmi_ioctl(struct inode *inode,
|
||||
goto recv_putback_on_err;
|
||||
}
|
||||
|
||||
up(&(priv->recv_sem));
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
ipmi_free_recv_msg(msg);
|
||||
break;
|
||||
|
||||
@ -362,11 +362,11 @@ static int ipmi_ioctl(struct inode *inode,
|
||||
spin_lock_irqsave(&(priv->recv_msg_lock), flags);
|
||||
list_add(entry, &(priv->recv_msgs));
|
||||
spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
|
||||
up(&(priv->recv_sem));
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
break;
|
||||
|
||||
recv_err:
|
||||
up(&(priv->recv_sem));
|
||||
mutex_unlock(&priv->recv_mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ipmi.h>
|
||||
#include <linux/ipmi_smi.h>
|
||||
@ -234,7 +235,7 @@ struct ipmi_smi
|
||||
|
||||
/* The list of command receivers that are registered for commands
|
||||
on this interface. */
|
||||
struct semaphore cmd_rcvrs_lock;
|
||||
struct mutex cmd_rcvrs_mutex;
|
||||
struct list_head cmd_rcvrs;
|
||||
|
||||
/* Events that were queues because no one was there to receive
|
||||
@ -387,10 +388,10 @@ static void clean_up_interface_data(ipmi_smi_t intf)
|
||||
|
||||
/* Wholesale remove all the entries from the list in the
|
||||
* interface and wait for RCU to know that none are in use. */
|
||||
down(&intf->cmd_rcvrs_lock);
|
||||
mutex_lock(&intf->cmd_rcvrs_mutex);
|
||||
list_add_rcu(&list, &intf->cmd_rcvrs);
|
||||
list_del_rcu(&intf->cmd_rcvrs);
|
||||
up(&intf->cmd_rcvrs_lock);
|
||||
mutex_unlock(&intf->cmd_rcvrs_mutex);
|
||||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(rcvr, rcvr2, &list, link)
|
||||
@ -846,7 +847,7 @@ int ipmi_destroy_user(ipmi_user_t user)
|
||||
* since other things may be using it till we do
|
||||
* synchronize_rcu()) then free everything in that list.
|
||||
*/
|
||||
down(&intf->cmd_rcvrs_lock);
|
||||
mutex_lock(&intf->cmd_rcvrs_mutex);
|
||||
list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
|
||||
if (rcvr->user == user) {
|
||||
list_del_rcu(&rcvr->link);
|
||||
@ -854,7 +855,7 @@ int ipmi_destroy_user(ipmi_user_t user)
|
||||
rcvrs = rcvr;
|
||||
}
|
||||
}
|
||||
up(&intf->cmd_rcvrs_lock);
|
||||
mutex_unlock(&intf->cmd_rcvrs_mutex);
|
||||
synchronize_rcu();
|
||||
while (rcvrs) {
|
||||
rcvr = rcvrs;
|
||||
@ -984,7 +985,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
|
||||
rcvr->netfn = netfn;
|
||||
rcvr->user = user;
|
||||
|
||||
down(&intf->cmd_rcvrs_lock);
|
||||
mutex_lock(&intf->cmd_rcvrs_mutex);
|
||||
/* Make sure the command/netfn is not already registered. */
|
||||
entry = find_cmd_rcvr(intf, netfn, cmd);
|
||||
if (entry) {
|
||||
@ -995,7 +996,7 @@ int ipmi_register_for_cmd(ipmi_user_t user,
|
||||
list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
|
||||
|
||||
out_unlock:
|
||||
up(&intf->cmd_rcvrs_lock);
|
||||
mutex_unlock(&intf->cmd_rcvrs_mutex);
|
||||
if (rv)
|
||||
kfree(rcvr);
|
||||
|
||||
@ -1009,17 +1010,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user,
|
||||
ipmi_smi_t intf = user->intf;
|
||||
struct cmd_rcvr *rcvr;
|
||||
|
||||
down(&intf->cmd_rcvrs_lock);
|
||||
mutex_lock(&intf->cmd_rcvrs_mutex);
|
||||
/* Make sure the command/netfn is not already registered. */
|
||||
rcvr = find_cmd_rcvr(intf, netfn, cmd);
|
||||
if ((rcvr) && (rcvr->user == user)) {
|
||||
list_del_rcu(&rcvr->link);
|
||||
up(&intf->cmd_rcvrs_lock);
|
||||
mutex_unlock(&intf->cmd_rcvrs_mutex);
|
||||
synchronize_rcu();
|
||||
kfree(rcvr);
|
||||
return 0;
|
||||
} else {
|
||||
up(&intf->cmd_rcvrs_lock);
|
||||
mutex_unlock(&intf->cmd_rcvrs_mutex);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
@ -2365,7 +2366,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
|
||||
spin_lock_init(&intf->events_lock);
|
||||
INIT_LIST_HEAD(&intf->waiting_events);
|
||||
intf->waiting_events_count = 0;
|
||||
init_MUTEX(&intf->cmd_rcvrs_lock);
|
||||
mutex_init(&intf->cmd_rcvrs_mutex);
|
||||
INIT_LIST_HEAD(&intf->cmd_rcvrs);
|
||||
init_waitqueue_head(&intf->waitq);
|
||||
|
||||
|
@ -1014,7 +1014,7 @@ static struct ipmi_smi_handlers handlers =
|
||||
|
||||
#define SI_MAX_PARMS 4
|
||||
static LIST_HEAD(smi_infos);
|
||||
static DECLARE_MUTEX(smi_infos_lock);
|
||||
static DEFINE_MUTEX(smi_infos_lock);
|
||||
static int smi_num; /* Used to sequence the SMIs */
|
||||
|
||||
#define DEFAULT_REGSPACING 1
|
||||
@ -2276,7 +2276,7 @@ static int try_smi_init(struct smi_info *new_smi)
|
||||
new_smi->slave_addr, new_smi->irq);
|
||||
}
|
||||
|
||||
down(&smi_infos_lock);
|
||||
mutex_lock(&smi_infos_lock);
|
||||
if (!is_new_interface(new_smi)) {
|
||||
printk(KERN_WARNING "ipmi_si: duplicate interface\n");
|
||||
rv = -EBUSY;
|
||||
@ -2432,7 +2432,7 @@ static int try_smi_init(struct smi_info *new_smi)
|
||||
|
||||
list_add_tail(&new_smi->link, &smi_infos);
|
||||
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
|
||||
printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
|
||||
|
||||
@ -2469,7 +2469,7 @@ static int try_smi_init(struct smi_info *new_smi)
|
||||
|
||||
kfree(new_smi);
|
||||
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -2527,26 +2527,26 @@ static __devinit int init_ipmi_si(void)
|
||||
#endif
|
||||
|
||||
if (si_trydefaults) {
|
||||
down(&smi_infos_lock);
|
||||
mutex_lock(&smi_infos_lock);
|
||||
if (list_empty(&smi_infos)) {
|
||||
/* No BMC was found, try defaults. */
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
default_find_bmc();
|
||||
} else {
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
}
|
||||
}
|
||||
|
||||
down(&smi_infos_lock);
|
||||
mutex_lock(&smi_infos_lock);
|
||||
if (list_empty(&smi_infos)) {
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
#ifdef CONFIG_PCI
|
||||
pci_unregister_driver(&ipmi_pci_driver);
|
||||
#endif
|
||||
printk("ipmi_si: Unable to find any System Interface(s)\n");
|
||||
return -ENODEV;
|
||||
} else {
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -2622,10 +2622,10 @@ static __exit void cleanup_ipmi_si(void)
|
||||
pci_unregister_driver(&ipmi_pci_driver);
|
||||
#endif
|
||||
|
||||
down(&smi_infos_lock);
|
||||
mutex_lock(&smi_infos_lock);
|
||||
list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
|
||||
cleanup_one_si(e);
|
||||
up(&smi_infos_lock);
|
||||
mutex_unlock(&smi_infos_lock);
|
||||
|
||||
driver_unregister(&ipmi_driver);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
@ -303,21 +304,22 @@ static int ipmi_heartbeat(void);
|
||||
static void panic_halt_ipmi_heartbeat(void);
|
||||
|
||||
|
||||
/* We use a semaphore to make sure that only one thing can send a set
|
||||
/* We use a mutex to make sure that only one thing can send a set
|
||||
timeout at one time, because we only have one copy of the data.
|
||||
The semaphore is claimed when the set_timeout is sent and freed
|
||||
The mutex is claimed when the set_timeout is sent and freed
|
||||
when both messages are free. */
|
||||
static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
|
||||
static DECLARE_MUTEX(set_timeout_lock);
|
||||
static DEFINE_MUTEX(set_timeout_lock);
|
||||
static DECLARE_COMPLETION(set_timeout_wait);
|
||||
static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
|
||||
{
|
||||
if (atomic_dec_and_test(&set_timeout_tofree))
|
||||
up(&set_timeout_lock);
|
||||
complete(&set_timeout_wait);
|
||||
}
|
||||
static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
|
||||
{
|
||||
if (atomic_dec_and_test(&set_timeout_tofree))
|
||||
up(&set_timeout_lock);
|
||||
complete(&set_timeout_wait);
|
||||
}
|
||||
static struct ipmi_smi_msg set_timeout_smi_msg =
|
||||
{
|
||||
@ -399,7 +401,7 @@ static int ipmi_set_timeout(int do_heartbeat)
|
||||
|
||||
|
||||
/* We can only send one of these at a time. */
|
||||
down(&set_timeout_lock);
|
||||
mutex_lock(&set_timeout_lock);
|
||||
|
||||
atomic_set(&set_timeout_tofree, 2);
|
||||
|
||||
@ -407,16 +409,21 @@ static int ipmi_set_timeout(int do_heartbeat)
|
||||
&set_timeout_recv_msg,
|
||||
&send_heartbeat_now);
|
||||
if (rv) {
|
||||
up(&set_timeout_lock);
|
||||
} else {
|
||||
if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
|
||||
|| ((send_heartbeat_now)
|
||||
&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
|
||||
{
|
||||
rv = ipmi_heartbeat();
|
||||
}
|
||||
mutex_unlock(&set_timeout_lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wait_for_completion(&set_timeout_wait);
|
||||
|
||||
if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB)
|
||||
|| ((send_heartbeat_now)
|
||||
&& (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY)))
|
||||
{
|
||||
rv = ipmi_heartbeat();
|
||||
}
|
||||
mutex_unlock(&set_timeout_lock);
|
||||
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -458,17 +465,17 @@ static void panic_halt_ipmi_set_timeout(void)
|
||||
The semaphore is claimed when the set_timeout is sent and freed
|
||||
when both messages are free. */
|
||||
static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
|
||||
static DECLARE_MUTEX(heartbeat_lock);
|
||||
static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
|
||||
static DEFINE_MUTEX(heartbeat_lock);
|
||||
static DECLARE_COMPLETION(heartbeat_wait);
|
||||
static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
|
||||
{
|
||||
if (atomic_dec_and_test(&heartbeat_tofree))
|
||||
up(&heartbeat_wait_lock);
|
||||
complete(&heartbeat_wait);
|
||||
}
|
||||
static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
|
||||
{
|
||||
if (atomic_dec_and_test(&heartbeat_tofree))
|
||||
up(&heartbeat_wait_lock);
|
||||
complete(&heartbeat_wait);
|
||||
}
|
||||
static struct ipmi_smi_msg heartbeat_smi_msg =
|
||||
{
|
||||
@ -511,14 +518,14 @@ static int ipmi_heartbeat(void)
|
||||
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
|
||||
}
|
||||
|
||||
down(&heartbeat_lock);
|
||||
mutex_lock(&heartbeat_lock);
|
||||
|
||||
atomic_set(&heartbeat_tofree, 2);
|
||||
|
||||
/* Don't reset the timer if we have the timer turned off, that
|
||||
re-enables the watchdog. */
|
||||
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
|
||||
up(&heartbeat_lock);
|
||||
mutex_unlock(&heartbeat_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -539,14 +546,14 @@ static int ipmi_heartbeat(void)
|
||||
&heartbeat_recv_msg,
|
||||
1);
|
||||
if (rv) {
|
||||
up(&heartbeat_lock);
|
||||
mutex_unlock(&heartbeat_lock);
|
||||
printk(KERN_WARNING PFX "heartbeat failure: %d\n",
|
||||
rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Wait for the heartbeat to be sent. */
|
||||
down(&heartbeat_wait_lock);
|
||||
wait_for_completion(&heartbeat_wait);
|
||||
|
||||
if (heartbeat_recv_msg.msg.data[0] != 0) {
|
||||
/* Got an error in the heartbeat response. It was already
|
||||
@ -555,7 +562,7 @@ static int ipmi_heartbeat(void)
|
||||
rv = -EINVAL;
|
||||
}
|
||||
|
||||
up(&heartbeat_lock);
|
||||
mutex_unlock(&heartbeat_lock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user