summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorHari Kanigeri <h-kanigeri2@ti.com>2011-05-31 09:24:35 +0100
committerAndy Green <andy.green@linaro.org>2011-05-31 11:06:03 +0100
commit0b97fddf6f6e984103ea1a615375b7193659e6cd (patch)
treea5e0b881bd0bcad80997ca44abfd57b3006d223f /arch
parent54fc820eaf9a50fb624dd499ab0172974132e938 (diff)
omap:iommu-notifier callback mechanism for mmu events
Implement notifier callback mechanism for IOMMU events such as MMU fault and file close. The Error handler that hooks to this registration would notify the remote processor whenever a process closed the iommu. This is to ensure that the Processes on Remote process stop accessing the buffers mapped by the terminating Process Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com> Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h14
-rw-r--r--arch/arm/plat-omap/iommu.c26
2 files changed, 37 insertions, 3 deletions
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 1959ecbafb1..8c737be12fb 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -48,6 +48,9 @@ struct iommu {
struct list_head mmap;
struct mutex mmap_lock; /* protect mmap */
int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
+
+ struct blocking_notifier_head notifier;
+
void *ctx; /* iommu context: registres saved area */
u32 da_start;
u32 da_end;
@@ -108,6 +111,11 @@ struct iommu_functions {
ssize_t (*dump_ctx)(struct iommu *obj, char *buf, ssize_t len);
};
+enum {
+ IOMMU_FAULT,
+ IOMMU_CLOSE,
+};
+
struct iommu_platform_data {
const char *name;
const char *oh_name;
@@ -163,6 +171,12 @@ extern u32 iommu_arch_version(void);
extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
extern u32 iotlb_cr_to_virt(struct cr_regs *cr);
+extern int iommu_register_notifier(struct iommu *obj,
+ struct notifier_block *nb);
+extern int iommu_unregister_notifier(struct iommu *obj,
+ struct notifier_block *nb);
+extern int iommu_notify_event(struct iommu *obj, int event, void *data);
+
extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
extern void iommu_set_twl(struct iommu *obj, bool on);
extern void flush_iotlb_page(struct iommu *obj, u32 da);
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 65e88f53411..737ccd156de 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -742,6 +742,26 @@ 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_register_notifier(struct iommu *obj, struct notifier_block *nb)
+{
+ if (!nb)
+ return -EINVAL;
+ return blocking_notifier_chain_register(&obj->notifier, nb);
+}
+EXPORT_SYMBOL_GPL(iommu_register_notifier);
+
+int iommu_unregister_notifier(struct iommu *obj, struct notifier_block *nb)
+{
+ if (!nb)
+ return -EINVAL;
+ return blocking_notifier_chain_unregister(&obj->notifier, nb);
+}
+EXPORT_SYMBOL_GPL(iommu_unregister_notifier);
+
/*
* Device IOMMU generic operations
*/
@@ -756,10 +776,9 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
eventfd_notification(obj);
/* Dynamic loading TLB or PTE */
- if (obj->isr)
- err = obj->isr(obj);
+ err = iommu_notify_event(obj, IOMMU_FAULT, data);
- if (!err)
+ if (err == NOTIFY_OK)
return IRQ_HANDLED;
stat = iommu_report_fault(obj, &da);
if (!stat)
@@ -935,6 +954,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);
err = request_irq(pdata->irq, iommu_fault_handler, IRQF_SHARED,
dev_name(&pdev->dev), obj);