mhi: dev: uci: block file open until MHI remove is complete
Race condition exists between open and remove where after open
obtain the device node and MHI remove frees the same device. To
avoid this scenario, block file open from obtaining device node
while remove is executing.
CRs-Fixed: 2356376
Change-Id: I1aad5c7848b791a2e03ea0acac643b9a2bda3ba2
Signed-off-by: Sujeev Dias <sdias@codeaurora.org>
diff --git a/drivers/bus/mhi/devices/mhi_uci.c b/drivers/bus/mhi/devices/mhi_uci.c
index af864d4..8b762c0 100644
--- a/drivers/bus/mhi/devices/mhi_uci.c
+++ b/drivers/bus/mhi/devices/mhi_uci.c
@@ -441,11 +441,10 @@
break;
}
}
- mutex_unlock(&mhi_uci_drv.lock);
/* could not find a minor node */
if (ret)
- return ret;
+ goto error_exit;
mutex_lock(&uci_dev->mutex);
if (!uci_dev->enabled) {
@@ -473,6 +472,7 @@
filp->private_data = uci_dev;
mutex_unlock(&uci_dev->mutex);
+ mutex_unlock(&mhi_uci_drv.lock);
return 0;
@@ -487,6 +487,9 @@
error_open_chan:
mutex_unlock(&uci_dev->mutex);
+error_exit:
+ mutex_unlock(&mhi_uci_drv.lock);
+
return ret;
}
@@ -505,8 +508,11 @@
MSG_LOG("Enter\n");
- /* disable the node */
+
+ mutex_lock(&mhi_uci_drv.lock);
mutex_lock(&uci_dev->mutex);
+
+ /* disable the node */
spin_lock_irq(&uci_dev->dl_chan.lock);
spin_lock_irq(&uci_dev->ul_chan.lock);
uci_dev->enabled = false;
@@ -518,9 +524,7 @@
/* delete the node to prevent new opens */
device_destroy(mhi_uci_drv.class, uci_dev->devt);
uci_dev->dev = NULL;
- mutex_lock(&mhi_uci_drv.lock);
list_del(&uci_dev->node);
- mutex_unlock(&mhi_uci_drv.lock);
/* safe to free memory only if all file nodes are closed */
if (!uci_dev->ref_count) {
@@ -528,11 +532,14 @@
mutex_destroy(&uci_dev->mutex);
clear_bit(MINOR(uci_dev->devt), uci_minors);
kfree(uci_dev);
+ mutex_unlock(&mhi_uci_drv.lock);
return;
}
MSG_LOG("Exit\n");
mutex_unlock(&uci_dev->mutex);
+ mutex_unlock(&mhi_uci_drv.lock);
+
}
static int mhi_uci_probe(struct mhi_device *mhi_dev,