summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorHari Kanigeri <h-kanigeri2@ti.com>2010-10-04 11:06:59 -0500
committerRicardo Perez Olivares <x0081762@ti.com>2010-10-06 12:39:54 -0500
commit9152c0999526b6df55df3b7d6a11583dd24c3281 (patch)
treef6178caca3f3477e26282db346b8372ec962ebc9 /arch
parentf6317a75f3841ece523c9a5a300314f6f5a111ee (diff)
omap:iommu-event notification shouldn't be blocking call
iommu_notify_event function is called from interrupt context, and this function is using internally blocking_notifier_call_chain call that could sleep. The fix is changing blocking_notifier to raw_notifier and let the callers of the iommu_notify_event handle the protection. iommu_notify_event is used for 2 purposes. One is for MMU FAULT notification to the device handler where the devh sets the error state to Fault and prevents the broadcasting of any iommu close notifications. This shouldn't be blocking. Second, it is used to broadcast the notifications of the Process ID that closed the iommu handle to remote processor. This could be blocking. Reported by Hari Nagalla Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com> Signed-off-by: Hari Nagalla <hnagalla@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-omap/dmm_user.c10
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h2
-rw-r--r--arch/arm/plat-omap/iommu.c11
3 files changed, 16 insertions, 7 deletions
diff --git a/arch/arm/plat-omap/dmm_user.c b/arch/arm/plat-omap/dmm_user.c
index 30f8bedee140..3afa28db3d2d 100644
--- a/arch/arm/plat-omap/dmm_user.c
+++ b/arch/arm/plat-omap/dmm_user.c
@@ -244,7 +244,15 @@ static int omap_dmm_release(struct inode *inode, struct file *filp)
}
obj = filp->private_data;
flush_signals(current);
- iommu_notify_event(obj->iovmm->iommu, IOMMU_CLOSE, NULL);
+
+ status = mutex_lock_interruptible(&obj->iovmm->dmm_map_lock);
+ if (status == 0) {
+ iommu_notify_event(obj->iovmm->iommu, IOMMU_CLOSE, NULL);
+ mutex_unlock(&obj->iovmm->dmm_map_lock);
+ } else {
+ pr_err("%s mutex_lock_interruptible returned 0x%x\n",
+ __func__, status);
+ }
user_remove_resources(obj);
iommu_put(obj->iovmm->iommu);
kfree(obj);
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 2d949d4947d1..80311a1684fd 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -46,7 +46,7 @@ struct iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
- struct blocking_notifier_head notifier;
+ struct raw_notifier_head notifier;
struct iotlb_entry *tlbs_e;/* iommu tlbs context: saved area */
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index d5deb3e60007..d728af8aec6b 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -827,15 +827,16 @@ void eventfd_notification(struct iommu *obj)
eventfd_signal(fd_reg->evt_ctx, 1);
}
-int iommu_notify_event(struct iommu *obj, int event, void *data) {
- return blocking_notifier_call_chain(&obj->notifier, event, data);
+int iommu_notify_event(struct iommu *obj, int event, void *data)
+{
+ return raw_notifier_call_chain(&obj->notifier, event, data);
}
int iommu_register_notifier(struct iommu *obj, struct notifier_block *nb)
{
if (!nb)
return -EINVAL;
- return blocking_notifier_chain_register(&obj->notifier, nb);
+ return raw_notifier_chain_register(&obj->notifier, nb);
}
EXPORT_SYMBOL_GPL(iommu_register_notifier);
@@ -843,7 +844,7 @@ int iommu_unregister_notifier(struct iommu *obj, struct notifier_block *nb)
{
if (!nb)
return -EINVAL;
- return blocking_notifier_chain_unregister(&obj->notifier, nb);
+ return raw_notifier_chain_unregister(&obj->notifier, nb);
}
EXPORT_SYMBOL_GPL(iommu_unregister_notifier);
@@ -995,7 +996,7 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&obj->event_list);
obj->regbase = pdata->io_base;
- BLOCKING_INIT_NOTIFIER_HEAD(&obj->notifier);
+ RAW_INIT_NOTIFIER_HEAD(&obj->notifier);
err = request_irq(pdata->irq, iommu_fault_handler, IRQF_SHARED,
dev_name(&pdev->dev), obj);