summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHari Kanigeri <h-kanigeri2@ti.com>2011-10-25 10:50:49 +0800
committerAndy Green <andy.green@linaro.org>2011-10-25 10:50:49 +0800
commit9cc39670423ea3a33653c1855d9cec1d6824c403 (patch)
treee1ffc376a33de30f95228b546d1ded1b6f7bf1e8
parent7617cc1163350d4e8eeaaae65ae7c31ce6c488e4 (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>
-rw-r--r--arch/arm/plat-omap/include/plat/iommu.h13
-rw-r--r--arch/arm/plat-omap/iommu.c27
2 files changed, 39 insertions, 1 deletions
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 5c6a4821c5f..5fd42f6547c 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -48,7 +48,7 @@ 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;
@@ -110,6 +110,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;
@@ -165,6 +170,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 9e728d34266..ec6e20c7643 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -746,6 +746,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
*/
@@ -759,6 +779,12 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
return IRQ_NONE;
eventfd_notification(obj);
+ /* Dynamic loading TLB or PTE */
+ errs = iommu_notify_event(obj, IOMMU_FAULT, data);
+
+ if (errs == NOTIFY_OK)
+ return IRQ_HANDLED;
+
errs = iommu_report_fault(obj, &da);
if (errs == 0)
return IRQ_HANDLED;
@@ -937,6 +963,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);