aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/iommu.c')
-rw-r--r--arch/powerpc/kernel/iommu.c69
1 files changed, 11 insertions, 58 deletions
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index f0dc680e659a..9d5d109f15c0 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -47,6 +47,7 @@
47#include <asm/fadump.h> 47#include <asm/fadump.h>
48#include <asm/vio.h> 48#include <asm/vio.h>
49#include <asm/tce.h> 49#include <asm/tce.h>
50#include <asm/mmu_context.h>
50 51
51#define DBG(...) 52#define DBG(...)
52 53
@@ -993,15 +994,19 @@ int iommu_tce_check_gpa(unsigned long page_shift, unsigned long gpa)
993} 994}
994EXPORT_SYMBOL_GPL(iommu_tce_check_gpa); 995EXPORT_SYMBOL_GPL(iommu_tce_check_gpa);
995 996
996long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry, 997long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl,
997 unsigned long *hpa, enum dma_data_direction *direction) 998 unsigned long entry, unsigned long *hpa,
999 enum dma_data_direction *direction)
998{ 1000{
999 long ret; 1001 long ret;
1002 unsigned long size = 0;
1000 1003
1001 ret = tbl->it_ops->exchange(tbl, entry, hpa, direction); 1004 ret = tbl->it_ops->exchange(tbl, entry, hpa, direction);
1002 1005
1003 if (!ret && ((*direction == DMA_FROM_DEVICE) || 1006 if (!ret && ((*direction == DMA_FROM_DEVICE) ||
1004 (*direction == DMA_BIDIRECTIONAL))) 1007 (*direction == DMA_BIDIRECTIONAL)) &&
1008 !mm_iommu_is_devmem(mm, *hpa, tbl->it_page_shift,
1009 &size))
1005 SetPageDirty(pfn_to_page(*hpa >> PAGE_SHIFT)); 1010 SetPageDirty(pfn_to_page(*hpa >> PAGE_SHIFT));
1006 1011
1007 /* if (unlikely(ret)) 1012 /* if (unlikely(ret))
@@ -1073,11 +1078,8 @@ void iommu_release_ownership(struct iommu_table *tbl)
1073} 1078}
1074EXPORT_SYMBOL_GPL(iommu_release_ownership); 1079EXPORT_SYMBOL_GPL(iommu_release_ownership);
1075 1080
1076int iommu_add_device(struct device *dev) 1081int iommu_add_device(struct iommu_table_group *table_group, struct device *dev)
1077{ 1082{
1078 struct iommu_table *tbl;
1079 struct iommu_table_group_link *tgl;
1080
1081 /* 1083 /*
1082 * The sysfs entries should be populated before 1084 * The sysfs entries should be populated before
1083 * binding IOMMU group. If sysfs entries isn't 1085 * binding IOMMU group. If sysfs entries isn't
@@ -1093,32 +1095,10 @@ int iommu_add_device(struct device *dev)
1093 return -EBUSY; 1095 return -EBUSY;
1094 } 1096 }
1095 1097
1096 tbl = get_iommu_table_base(dev);
1097 if (!tbl) {
1098 pr_debug("%s: Skipping device %s with no tbl\n",
1099 __func__, dev_name(dev));
1100 return 0;
1101 }
1102
1103 tgl = list_first_entry_or_null(&tbl->it_group_list,
1104 struct iommu_table_group_link, next);
1105 if (!tgl) {
1106 pr_debug("%s: Skipping device %s with no group\n",
1107 __func__, dev_name(dev));
1108 return 0;
1109 }
1110 pr_debug("%s: Adding %s to iommu group %d\n", 1098 pr_debug("%s: Adding %s to iommu group %d\n",
1111 __func__, dev_name(dev), 1099 __func__, dev_name(dev), iommu_group_id(table_group->group));
1112 iommu_group_id(tgl->table_group->group));
1113
1114 if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) {
1115 pr_err("%s: Invalid IOMMU page size %lx (%lx) on %s\n",
1116 __func__, IOMMU_PAGE_SIZE(tbl),
1117 PAGE_SIZE, dev_name(dev));
1118 return -EINVAL;
1119 }
1120 1100
1121 return iommu_group_add_device(tgl->table_group->group, dev); 1101 return iommu_group_add_device(table_group->group, dev);
1122} 1102}
1123EXPORT_SYMBOL_GPL(iommu_add_device); 1103EXPORT_SYMBOL_GPL(iommu_add_device);
1124 1104
@@ -1138,31 +1118,4 @@ void iommu_del_device(struct device *dev)
1138 iommu_group_remove_device(dev); 1118 iommu_group_remove_device(dev);
1139} 1119}
1140EXPORT_SYMBOL_GPL(iommu_del_device); 1120EXPORT_SYMBOL_GPL(iommu_del_device);
1141
1142static int tce_iommu_bus_notifier(struct notifier_block *nb,
1143 unsigned long action, void *data)
1144{
1145 struct device *dev = data;
1146
1147 switch (action) {
1148 case BUS_NOTIFY_ADD_DEVICE:
1149 return iommu_add_device(dev);
1150 case BUS_NOTIFY_DEL_DEVICE:
1151 if (dev->iommu_group)
1152 iommu_del_device(dev);
1153 return 0;
1154 default:
1155 return 0;
1156 }
1157}
1158
1159static struct notifier_block tce_iommu_bus_nb = {
1160 .notifier_call = tce_iommu_bus_notifier,
1161};
1162
1163int __init tce_iommu_bus_notifier_init(void)
1164{
1165 bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
1166 return 0;
1167}
1168#endif /* CONFIG_IOMMU_API */ 1121#endif /* CONFIG_IOMMU_API */