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