diff options
| author | Hari Kanigeri <h-kanigeri2@ti.com> | 2011-05-31 09:24:41 +0100 |
|---|---|---|
| committer | Andy Green <andy.green@linaro.org> | 2011-05-31 11:06:12 +0100 |
| commit | f0839fde63b23031ccc7eff8a6e2051bbd42bda7 (patch) | |
| tree | db450b8a3e309cf38d9a09172375ab2cc3521819 /arch | |
| parent | 3413b4f308890b9cff5c1b8552931e5cf9e64e3b (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.c | 10 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/iommu.h | 2 | ||||
| -rw-r--r-- | arch/arm/plat-omap/iommu.c | 11 |
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 30f8bedee14..3afa28db3d2 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 c1b3f6ef203..cdccd7a969f 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -49,7 +49,7 @@ struct iommu { struct mutex mmap_lock; /* protect mmap */ int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv); - struct blocking_notifier_head notifier; + struct raw_notifier_head notifier; u32 da_start; u32 da_end; diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index d86d47b6a5d..7af4a306537 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); @@ -1048,7 +1049,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); |
