This change makes dyn_id_lock a spinlock instead. The lock is only
protecting from concurrent accesses to the id & dyn_id_expiry members of
struct bmc_device, so we don't need to sleep while it's held.
Reported-by: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Jeremy Kerr <j...@ozlabs.org>
---
drivers/char/ipmi/ipmi_msghandler.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/char/ipmi/ipmi_msghandler.c
b/drivers/char/ipmi/ipmi_msghandler.c
index 9c82d55..7edb482 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -277,7 +277,7 @@ struct bmc_device {
ipmi_smi_t intf;
enum bmc_dyn_device_id_state dyn_id_state;
unsigned long dyn_id_expiry;
- struct mutex dyn_id_lock; /* protects id & dyn_id* fields */
+ spinlock_t dyn_id_lock; /* protects id & dyn_id* fields */
unsigned char guid[16];
int guid_set;
char name[16];
@@ -2087,6 +2087,7 @@ EXPORT_SYMBOL(ipmi_request_supply_msgs);
static void bmc_device_id_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
struct ipmi_device_id id;
+ unsigned long flags;
int rc;
if ((msg->addr.addr_type != IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
@@ -2098,7 +2099,7 @@ static void bmc_device_id_handler(ipmi_smi_t intf, struct
ipmi_recv_msg *msg)
* the mutex over the entire transaction), as we may be called after
* bmc_get_device_id has timed-out (and so released its mutex).
*/
- mutex_lock(&intf->bmc->dyn_id_lock);
+ spin_lock_irqsave(&intf->bmc->dyn_id_lock, flags);
rc = ipmi_demangle_device_id(msg->msg.netfn, msg->msg.cmd,
msg->msg.data, msg->msg.data_len, &id);
@@ -2117,7 +2118,7 @@ static void bmc_device_id_handler(ipmi_smi_t intf, struct
ipmi_recv_msg *msg)
intf->bmc->dyn_id_state = BMC_DEVICE_DYN_ID_STATE_VALID;
intf->bmc->dyn_id_expiry = jiffies + IPMI_DYN_DEV_ID_EXPIRY;
out:
- mutex_unlock(&intf->bmc->dyn_id_lock);
+ spin_unlock_irqrestore(&intf->bmc->dyn_id_lock, flags);
wake_up(&intf->waitq);
}
@@ -2127,17 +2128,18 @@ static int bmc_get_device_id(struct bmc_device *bmc, struct ipmi_device_id *id)
struct ipmi_system_interface_addr si;
ipmi_smi_t intf = bmc->intf;
struct kernel_ipmi_msg msg;
+ unsigned long flags;
bool query = false;
int tmp, rc = 0;
- mutex_lock(&bmc->dyn_id_lock);
+ spin_lock_irqsave(&bmc->dyn_id_lock, flags);
/* if we have a valid and current ID, just return that. */
if (bmc->dyn_id_state == BMC_DEVICE_DYN_ID_STATE_VALID &&
time_is_after_jiffies(bmc->dyn_id_expiry)) {
if (id)
*id = bmc->id;
- mutex_unlock(&bmc->dyn_id_lock);
+ spin_unlock_irqrestore(&bmc->dyn_id_lock, flags);
return 0;
}
@@ -2153,7 +2155,7 @@ static int bmc_get_device_id(struct bmc_device *bmc, struct ipmi_device_id *id)
/* We unlock here, as bmc_device_id_handler will need to re-acquire
* the mutex
*/
- mutex_unlock(&bmc->dyn_id_lock);
+ spin_unlock_irqrestore(&bmc->dyn_id_lock, flags);
/* Send Get Device ID request. */
if (query) {
@@ -2182,9 +2184,9 @@ static int bmc_get_device_id(struct bmc_device *bmc,
struct ipmi_device_id *id)
-1, 0);
if (rc) {
- mutex_lock(&bmc->dyn_id_lock);
+ spin_lock_irqsave(&bmc->dyn_id_lock, flags);
bmc->dyn_id_state = BMC_DEVICE_DYN_ID_STATE_INVALID;
- mutex_unlock(&bmc->dyn_id_lock);
+ spin_unlock_irqrestore(&bmc->dyn_id_lock, flags);
return rc;
}
}
@@ -2200,7 +2202,7 @@ static int bmc_get_device_id(struct bmc_device *bmc,
struct ipmi_device_id *id)
if (query)
intf->null_user_handler = NULL;
- mutex_lock(&bmc->dyn_id_lock);
+ spin_lock_irqsave(&bmc->dyn_id_lock, flags);
if (!tmp) {
/* timeout */
bmc->dyn_id_state = BMC_DEVICE_DYN_ID_STATE_INVALID;
@@ -2209,7 +2211,7 @@ static int bmc_get_device_id(struct bmc_device *bmc,
struct ipmi_device_id *id)
/* We didn't timeout, but another thread has started a new
* query after we'd dropped the lock. Wait for that thread
* instead. */
- mutex_unlock(&bmc->dyn_id_lock);
+ spin_unlock_irqrestore(&bmc->dyn_id_lock, flags);
goto retry;
} else if (bmc->dyn_id_state != BMC_DEVICE_DYN_ID_STATE_VALID) {
@@ -2219,7 +2221,7 @@ static int bmc_get_device_id(struct bmc_device *bmc,
struct ipmi_device_id *id)
*id = bmc->id;
}
- mutex_unlock(&intf->bmc->dyn_id_lock);
+ spin_unlock_irqrestore(&intf->bmc->dyn_id_lock, flags);
return rc;
}
@@ -2730,7 +2732,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum)
struct bmc_device *bmc = intf->bmc;
struct bmc_device *old_bmc;
- mutex_init(&bmc->dyn_id_lock);
+ spin_lock_init(&bmc->dyn_id_lock);
bmc_get_device_id(bmc, NULL);
mutex_lock(&ipmidriver_mutex);