diff options
Diffstat (limited to 'drivers/iommu/shmobile-iommu.c')
-rw-r--r-- | drivers/iommu/shmobile-iommu.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/iommu/shmobile-iommu.c b/drivers/iommu/shmobile-iommu.c index f1b00774e4de..a0287519a1d4 100644 --- a/drivers/iommu/shmobile-iommu.c +++ b/drivers/iommu/shmobile-iommu.c | |||
@@ -42,11 +42,17 @@ struct shmobile_iommu_domain { | |||
42 | spinlock_t map_lock; | 42 | spinlock_t map_lock; |
43 | spinlock_t attached_list_lock; | 43 | spinlock_t attached_list_lock; |
44 | struct list_head attached_list; | 44 | struct list_head attached_list; |
45 | struct iommu_domain domain; | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static struct shmobile_iommu_archdata *ipmmu_archdata; | 48 | static struct shmobile_iommu_archdata *ipmmu_archdata; |
48 | static struct kmem_cache *l1cache, *l2cache; | 49 | static struct kmem_cache *l1cache, *l2cache; |
49 | 50 | ||
51 | static struct shmobile_iommu_domain *to_sh_domain(struct iommu_domain *dom) | ||
52 | { | ||
53 | return container_of(dom, struct shmobile_iommu_domain, domain); | ||
54 | } | ||
55 | |||
50 | static int pgtable_alloc(struct shmobile_iommu_domain_pgtable *pgtable, | 56 | static int pgtable_alloc(struct shmobile_iommu_domain_pgtable *pgtable, |
51 | struct kmem_cache *cache, size_t size) | 57 | struct kmem_cache *cache, size_t size) |
52 | { | 58 | { |
@@ -82,31 +88,33 @@ static void pgtable_write(struct shmobile_iommu_domain_pgtable *pgtable, | |||
82 | sizeof(val) * count, DMA_TO_DEVICE); | 88 | sizeof(val) * count, DMA_TO_DEVICE); |
83 | } | 89 | } |
84 | 90 | ||
85 | static int shmobile_iommu_domain_init(struct iommu_domain *domain) | 91 | static struct iommu_domain *shmobile_iommu_domain_alloc(unsigned type) |
86 | { | 92 | { |
87 | struct shmobile_iommu_domain *sh_domain; | 93 | struct shmobile_iommu_domain *sh_domain; |
88 | int i, ret; | 94 | int i, ret; |
89 | 95 | ||
90 | sh_domain = kmalloc(sizeof(*sh_domain), GFP_KERNEL); | 96 | if (type != IOMMU_DOMAIN_UNMANAGED) |
97 | return NULL; | ||
98 | |||
99 | sh_domain = kzalloc(sizeof(*sh_domain), GFP_KERNEL); | ||
91 | if (!sh_domain) | 100 | if (!sh_domain) |
92 | return -ENOMEM; | 101 | return NULL; |
93 | ret = pgtable_alloc(&sh_domain->l1, l1cache, L1_SIZE); | 102 | ret = pgtable_alloc(&sh_domain->l1, l1cache, L1_SIZE); |
94 | if (ret < 0) { | 103 | if (ret < 0) { |
95 | kfree(sh_domain); | 104 | kfree(sh_domain); |
96 | return ret; | 105 | return NULL; |
97 | } | 106 | } |
98 | for (i = 0; i < L1_LEN; i++) | 107 | for (i = 0; i < L1_LEN; i++) |
99 | sh_domain->l2[i].pgtable = NULL; | 108 | sh_domain->l2[i].pgtable = NULL; |
100 | spin_lock_init(&sh_domain->map_lock); | 109 | spin_lock_init(&sh_domain->map_lock); |
101 | spin_lock_init(&sh_domain->attached_list_lock); | 110 | spin_lock_init(&sh_domain->attached_list_lock); |
102 | INIT_LIST_HEAD(&sh_domain->attached_list); | 111 | INIT_LIST_HEAD(&sh_domain->attached_list); |
103 | domain->priv = sh_domain; | 112 | return &sh_domain->domain; |
104 | return 0; | ||
105 | } | 113 | } |
106 | 114 | ||
107 | static void shmobile_iommu_domain_destroy(struct iommu_domain *domain) | 115 | static void shmobile_iommu_domain_free(struct iommu_domain *domain) |
108 | { | 116 | { |
109 | struct shmobile_iommu_domain *sh_domain = domain->priv; | 117 | struct shmobile_iommu_domain *sh_domain = to_sh_domain(domain); |
110 | int i; | 118 | int i; |
111 | 119 | ||
112 | for (i = 0; i < L1_LEN; i++) { | 120 | for (i = 0; i < L1_LEN; i++) { |
@@ -115,14 +123,13 @@ static void shmobile_iommu_domain_destroy(struct iommu_domain *domain) | |||
115 | } | 123 | } |
116 | pgtable_free(&sh_domain->l1, l1cache, L1_SIZE); | 124 | pgtable_free(&sh_domain->l1, l1cache, L1_SIZE); |
117 | kfree(sh_domain); | 125 | kfree(sh_domain); |
118 | domain->priv = NULL; | ||
119 | } | 126 | } |
120 | 127 | ||
121 | static int shmobile_iommu_attach_device(struct iommu_domain *domain, | 128 | static int shmobile_iommu_attach_device(struct iommu_domain *domain, |
122 | struct device *dev) | 129 | struct device *dev) |
123 | { | 130 | { |
124 | struct shmobile_iommu_archdata *archdata = dev->archdata.iommu; | 131 | struct shmobile_iommu_archdata *archdata = dev->archdata.iommu; |
125 | struct shmobile_iommu_domain *sh_domain = domain->priv; | 132 | struct shmobile_iommu_domain *sh_domain = to_sh_domain(domain); |
126 | int ret = -EBUSY; | 133 | int ret = -EBUSY; |
127 | 134 | ||
128 | if (!archdata) | 135 | if (!archdata) |
@@ -151,7 +158,7 @@ static void shmobile_iommu_detach_device(struct iommu_domain *domain, | |||
151 | struct device *dev) | 158 | struct device *dev) |
152 | { | 159 | { |
153 | struct shmobile_iommu_archdata *archdata = dev->archdata.iommu; | 160 | struct shmobile_iommu_archdata *archdata = dev->archdata.iommu; |
154 | struct shmobile_iommu_domain *sh_domain = domain->priv; | 161 | struct shmobile_iommu_domain *sh_domain = to_sh_domain(domain); |
155 | 162 | ||
156 | if (!archdata) | 163 | if (!archdata) |
157 | return; | 164 | return; |
@@ -214,7 +221,7 @@ static int shmobile_iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
214 | phys_addr_t paddr, size_t size, int prot) | 221 | phys_addr_t paddr, size_t size, int prot) |
215 | { | 222 | { |
216 | struct shmobile_iommu_domain_pgtable l2 = { .pgtable = NULL }; | 223 | struct shmobile_iommu_domain_pgtable l2 = { .pgtable = NULL }; |
217 | struct shmobile_iommu_domain *sh_domain = domain->priv; | 224 | struct shmobile_iommu_domain *sh_domain = to_sh_domain(domain); |
218 | unsigned int l1index, l2index; | 225 | unsigned int l1index, l2index; |
219 | int ret; | 226 | int ret; |
220 | 227 | ||
@@ -258,7 +265,7 @@ static size_t shmobile_iommu_unmap(struct iommu_domain *domain, | |||
258 | unsigned long iova, size_t size) | 265 | unsigned long iova, size_t size) |
259 | { | 266 | { |
260 | struct shmobile_iommu_domain_pgtable l2 = { .pgtable = NULL }; | 267 | struct shmobile_iommu_domain_pgtable l2 = { .pgtable = NULL }; |
261 | struct shmobile_iommu_domain *sh_domain = domain->priv; | 268 | struct shmobile_iommu_domain *sh_domain = to_sh_domain(domain); |
262 | unsigned int l1index, l2index; | 269 | unsigned int l1index, l2index; |
263 | uint32_t l2entry = 0; | 270 | uint32_t l2entry = 0; |
264 | size_t ret = 0; | 271 | size_t ret = 0; |
@@ -298,7 +305,7 @@ done: | |||
298 | static phys_addr_t shmobile_iommu_iova_to_phys(struct iommu_domain *domain, | 305 | static phys_addr_t shmobile_iommu_iova_to_phys(struct iommu_domain *domain, |
299 | dma_addr_t iova) | 306 | dma_addr_t iova) |
300 | { | 307 | { |
301 | struct shmobile_iommu_domain *sh_domain = domain->priv; | 308 | struct shmobile_iommu_domain *sh_domain = to_sh_domain(domain); |
302 | uint32_t l1entry = 0, l2entry = 0; | 309 | uint32_t l1entry = 0, l2entry = 0; |
303 | unsigned int l1index, l2index; | 310 | unsigned int l1index, l2index; |
304 | 311 | ||
@@ -355,8 +362,8 @@ static int shmobile_iommu_add_device(struct device *dev) | |||
355 | } | 362 | } |
356 | 363 | ||
357 | static const struct iommu_ops shmobile_iommu_ops = { | 364 | static const struct iommu_ops shmobile_iommu_ops = { |
358 | .domain_init = shmobile_iommu_domain_init, | 365 | .domain_alloc = shmobile_iommu_domain_alloc, |
359 | .domain_destroy = shmobile_iommu_domain_destroy, | 366 | .domain_free = shmobile_iommu_domain_free, |
360 | .attach_dev = shmobile_iommu_attach_device, | 367 | .attach_dev = shmobile_iommu_attach_device, |
361 | .detach_dev = shmobile_iommu_detach_device, | 368 | .detach_dev = shmobile_iommu_detach_device, |
362 | .map = shmobile_iommu_map, | 369 | .map = shmobile_iommu_map, |