diff options
author | David Cohen <dacohen@gmail.com> | 2011-02-16 14:35:51 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2011-02-24 17:23:17 -0500 |
commit | d594f1f31afe13edd8c02f3854a65cc58cfb3b74 (patch) | |
tree | 8986a9af7302b214316f9498d153be46c9c4df38 /arch/arm/plat-omap/iommu.c | |
parent | 92e753d7984db36f0a3c0bbf0f377da114768775 (diff) |
omap: IOMMU: add support to callback during fault handling
Add support to register an isr for IOMMU fault situations and adapt it
to allow such (*isr)() to be used as fault callback. Drivers using IOMMU
module might want to be informed when errors happen in order to debug it
or react.
Signed-off-by: David Cohen <dacohen@gmail.com>
Acked-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/plat-omap/iommu.c')
-rw-r--r-- | arch/arm/plat-omap/iommu.c | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 4b3218eaf3e5..e3eb0380090a 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c | |||
@@ -783,25 +783,19 @@ static void iopgtable_clear_entry_all(struct iommu *obj) | |||
783 | */ | 783 | */ |
784 | static irqreturn_t iommu_fault_handler(int irq, void *data) | 784 | static irqreturn_t iommu_fault_handler(int irq, void *data) |
785 | { | 785 | { |
786 | u32 stat, da; | 786 | u32 da, errs; |
787 | u32 *iopgd, *iopte; | 787 | u32 *iopgd, *iopte; |
788 | int err = -EIO; | ||
789 | struct iommu *obj = data; | 788 | struct iommu *obj = data; |
790 | 789 | ||
791 | if (!obj->refcount) | 790 | if (!obj->refcount) |
792 | return IRQ_NONE; | 791 | return IRQ_NONE; |
793 | 792 | ||
794 | /* Dynamic loading TLB or PTE */ | ||
795 | if (obj->isr) | ||
796 | err = obj->isr(obj); | ||
797 | |||
798 | if (!err) | ||
799 | return IRQ_HANDLED; | ||
800 | |||
801 | clk_enable(obj->clk); | 793 | clk_enable(obj->clk); |
802 | stat = iommu_report_fault(obj, &da); | 794 | errs = iommu_report_fault(obj, &da); |
803 | clk_disable(obj->clk); | 795 | clk_disable(obj->clk); |
804 | if (!stat) | 796 | |
797 | /* Fault callback or TLB/PTE Dynamic loading */ | ||
798 | if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv)) | ||
805 | return IRQ_HANDLED; | 799 | return IRQ_HANDLED; |
806 | 800 | ||
807 | iommu_disable(obj); | 801 | iommu_disable(obj); |
@@ -809,15 +803,16 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) | |||
809 | iopgd = iopgd_offset(obj, da); | 803 | iopgd = iopgd_offset(obj, da); |
810 | 804 | ||
811 | if (!iopgd_is_table(*iopgd)) { | 805 | if (!iopgd_is_table(*iopgd)) { |
812 | dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", obj->name, | 806 | dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p " |
813 | da, iopgd, *iopgd); | 807 | "*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd); |
814 | return IRQ_NONE; | 808 | return IRQ_NONE; |
815 | } | 809 | } |
816 | 810 | ||
817 | iopte = iopte_offset(iopgd, da); | 811 | iopte = iopte_offset(iopgd, da); |
818 | 812 | ||
819 | dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", | 813 | dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x " |
820 | obj->name, da, iopgd, *iopgd, iopte, *iopte); | 814 | "pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd, |
815 | iopte, *iopte); | ||
821 | 816 | ||
822 | return IRQ_NONE; | 817 | return IRQ_NONE; |
823 | } | 818 | } |
@@ -920,6 +915,33 @@ void iommu_put(struct iommu *obj) | |||
920 | } | 915 | } |
921 | EXPORT_SYMBOL_GPL(iommu_put); | 916 | EXPORT_SYMBOL_GPL(iommu_put); |
922 | 917 | ||
918 | int iommu_set_isr(const char *name, | ||
919 | int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, | ||
920 | void *priv), | ||
921 | void *isr_priv) | ||
922 | { | ||
923 | struct device *dev; | ||
924 | struct iommu *obj; | ||
925 | |||
926 | dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name, | ||
927 | device_match_by_alias); | ||
928 | if (!dev) | ||
929 | return -ENODEV; | ||
930 | |||
931 | obj = to_iommu(dev); | ||
932 | mutex_lock(&obj->iommu_lock); | ||
933 | if (obj->refcount != 0) { | ||
934 | mutex_unlock(&obj->iommu_lock); | ||
935 | return -EBUSY; | ||
936 | } | ||
937 | obj->isr = isr; | ||
938 | obj->isr_priv = isr_priv; | ||
939 | mutex_unlock(&obj->iommu_lock); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | EXPORT_SYMBOL_GPL(iommu_set_isr); | ||
944 | |||
923 | /* | 945 | /* |
924 | * OMAP Device MMU(IOMMU) detection | 946 | * OMAP Device MMU(IOMMU) detection |
925 | */ | 947 | */ |