aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuman Anna2015-05-12 16:52:59 -0500
committerSuman Anna2019-03-03 17:39:54 -0600
commitd07f2e6c2ade8e7cc32088b095da1db996f0eab5 (patch)
tree288a253cb70cd63f282becfc37493c99a9f3e5a3
parentf7b2c293b8dce275d2c8ea247dd2a6b55cc8b6e1 (diff)
downloadiommu-d07f2e6c2ade8e7cc32088b095da1db996f0eab5.tar.gz
iommu-d07f2e6c2ade8e7cc32088b095da1db996f0eab5.tar.xz
iommu-d07f2e6c2ade8e7cc32088b095da1db996f0eab5.zip
iommu/omap: add logic to save/restore locked TLBs
The MMUs provide a mechanism to lock TLB entries to avoid eviction and fetching of frequently used page table entries. These TLBs lose context when the MMUs are turned OFF. Add the logic to save and restore these locked TLBS during suspend and resume respectively. There are no locked TLBs during initial power ON, and they need not be saved during final shutdown. Signed-off-by: Suman Anna <s-anna@ti.com>
-rw-r--r--drivers/iommu/omap-iommu.c61
-rw-r--r--drivers/iommu/omap-iommu.h3
2 files changed, 61 insertions, 3 deletions
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 4deb92105ad1..1042772341e1 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -887,15 +887,55 @@ static void omap_iommu_detach(struct omap_iommu *obj)
887 887
888 dma_unmap_single(obj->dev, obj->pd_dma, IOPGD_TABLE_SIZE, 888 dma_unmap_single(obj->dev, obj->pd_dma, IOPGD_TABLE_SIZE,
889 DMA_TO_DEVICE); 889 DMA_TO_DEVICE);
890 iommu_disable(obj);
891 obj->pd_dma = 0; 890 obj->pd_dma = 0;
892 obj->iopgd = NULL; 891 obj->iopgd = NULL;
892 iommu_disable(obj);
893 893
894 spin_unlock(&obj->iommu_lock); 894 spin_unlock(&obj->iommu_lock);
895 895
896 dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); 896 dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
897} 897}
898 898
899static void omap_iommu_save_tlb_entries(struct omap_iommu *obj)
900{
901 struct iotlb_lock lock;
902 struct cr_regs cr;
903 struct cr_regs *tmp;
904 int i;
905
906 /* check if there are any locked tlbs to save */
907 iotlb_lock_get(obj, &lock);
908 obj->num_cr_ctx = lock.base;
909 if (!obj->num_cr_ctx)
910 return;
911
912 tmp = obj->cr_ctx;
913 for_each_iotlb_cr(obj, obj->num_cr_ctx, i, cr)
914 *tmp++ = cr;
915}
916
917static void omap_iommu_restore_tlb_entries(struct omap_iommu *obj)
918{
919 struct iotlb_lock l;
920 struct cr_regs *tmp;
921 int i;
922
923 /* no locked tlbs to restore */
924 if (!obj->num_cr_ctx)
925 return;
926
927 l.base = 0;
928 tmp = obj->cr_ctx;
929 for (i = 0; i < obj->num_cr_ctx; i++, tmp++) {
930 l.vict = i;
931 iotlb_lock_set(obj, &l);
932 iotlb_load_cr(obj, tmp);
933 }
934 l.base = obj->num_cr_ctx;
935 l.vict = i;
936 iotlb_lock_set(obj, &l);
937}
938
899/** 939/**
900 * omap_iommu_runtime_suspend - disable an iommu device 940 * omap_iommu_runtime_suspend - disable an iommu device
901 * @dev: iommu device 941 * @dev: iommu device
@@ -905,7 +945,8 @@ static void omap_iommu_detach(struct omap_iommu *obj)
905 * device, or during system/runtime suspend of the device. This 945 * device, or during system/runtime suspend of the device. This
906 * includes programming all the appropriate IOMMU registers, and 946 * includes programming all the appropriate IOMMU registers, and
907 * managing the associated omap_hwmod's state and the device's 947 * managing the associated omap_hwmod's state and the device's
908 * reset line. 948 * reset line. This function also saves the context of any
949 * locked TLBs if suspending.
909 **/ 950 **/
910static int omap_iommu_runtime_suspend(struct device *dev) 951static int omap_iommu_runtime_suspend(struct device *dev)
911{ 952{
@@ -914,6 +955,10 @@ static int omap_iommu_runtime_suspend(struct device *dev)
914 struct omap_iommu *obj = to_iommu(dev); 955 struct omap_iommu *obj = to_iommu(dev);
915 int ret; 956 int ret;
916 957
958 /* save the TLBs only during suspend, and not for power down */
959 if (obj->domain && obj->iopgd)
960 omap_iommu_save_tlb_entries(obj);
961
917 omap2_iommu_disable(obj); 962 omap2_iommu_disable(obj);
918 963
919 if (pdata && pdata->device_idle) 964 if (pdata && pdata->device_idle)
@@ -942,7 +987,8 @@ static int omap_iommu_runtime_suspend(struct device *dev)
942 * device, or during system/runtime resume of the device. This 987 * device, or during system/runtime resume of the device. This
943 * includes programming all the appropriate IOMMU registers, and 988 * includes programming all the appropriate IOMMU registers, and
944 * managing the associated omap_hwmod's state and the device's 989 * managing the associated omap_hwmod's state and the device's
945 * reset line. 990 * reset line. The function also restores any locked TLBs if
991 * resuming after a suspend.
946 **/ 992 **/
947static int omap_iommu_runtime_resume(struct device *dev) 993static int omap_iommu_runtime_resume(struct device *dev)
948{ 994{
@@ -970,6 +1016,10 @@ static int omap_iommu_runtime_resume(struct device *dev)
970 if (pdata && pdata->device_enable) 1016 if (pdata && pdata->device_enable)
971 pdata->device_enable(pdev); 1017 pdata->device_enable(pdev);
972 1018
1019 /* restore the TLBs only during resume, and not for power up */
1020 if (obj->domain)
1021 omap_iommu_restore_tlb_entries(obj);
1022
973 ret = omap2_iommu_enable(obj); 1023 ret = omap2_iommu_enable(obj);
974 1024
975 return ret; 1025 return ret;
@@ -1070,6 +1120,11 @@ static int omap_iommu_probe(struct platform_device *pdev)
1070 1120
1071 obj->dev = &pdev->dev; 1121 obj->dev = &pdev->dev;
1072 obj->ctx = (void *)obj + sizeof(*obj); 1122 obj->ctx = (void *)obj + sizeof(*obj);
1123 obj->cr_ctx = devm_kzalloc(&pdev->dev,
1124 sizeof(*obj->cr_ctx) * obj->nr_tlb_entries,
1125 GFP_KERNEL);
1126 if (!obj->cr_ctx)
1127 return -ENOMEM;
1073 1128
1074 spin_lock_init(&obj->iommu_lock); 1129 spin_lock_init(&obj->iommu_lock);
1075 spin_lock_init(&obj->page_table_lock); 1130 spin_lock_init(&obj->page_table_lock);
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 7766d5a4f3f1..ca07fbf287d0 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -76,6 +76,9 @@ struct omap_iommu {
76 76
77 void *ctx; /* iommu context: registres saved area */ 77 void *ctx; /* iommu context: registres saved area */
78 78
79 struct cr_regs *cr_ctx;
80 u32 num_cr_ctx;
81
79 int has_bus_err_back; 82 int has_bus_err_back;
80 u32 id; 83 u32 id;
81 84