@@ -121,6 +121,22 @@ static inline int pt_entry_isvalid(unsigned long entry)
121
121
return (entry & ZPCI_PTE_VALID_MASK ) == ZPCI_PTE_VALID ;
122
122
}
123
123
124
+ static inline unsigned long * get_rf_rso (unsigned long entry )
125
+ {
126
+ if ((entry & ZPCI_TABLE_TYPE_MASK ) == ZPCI_TABLE_TYPE_RFX )
127
+ return phys_to_virt (entry & ZPCI_RTE_ADDR_MASK );
128
+ else
129
+ return NULL ;
130
+ }
131
+
132
+ static inline unsigned long * get_rs_rto (unsigned long entry )
133
+ {
134
+ if ((entry & ZPCI_TABLE_TYPE_MASK ) == ZPCI_TABLE_TYPE_RSX )
135
+ return phys_to_virt (entry & ZPCI_RTE_ADDR_MASK );
136
+ else
137
+ return NULL ;
138
+ }
139
+
124
140
static inline unsigned long * get_rt_sto (unsigned long entry )
125
141
{
126
142
if ((entry & ZPCI_TABLE_TYPE_MASK ) == ZPCI_TABLE_TYPE_RTX )
@@ -192,18 +208,59 @@ static void dma_free_seg_table(unsigned long entry)
192
208
dma_free_cpu_table (sto );
193
209
}
194
210
195
- static void dma_cleanup_tables (unsigned long * table )
211
+ static void dma_free_rt_table (unsigned long entry )
196
212
{
213
+ unsigned long * rto = get_rs_rto (entry );
197
214
int rtx ;
198
215
199
- if (!table )
216
+ for (rtx = 0 ; rtx < ZPCI_TABLE_ENTRIES ; rtx ++ )
217
+ if (reg_entry_isvalid (rto [rtx ]))
218
+ dma_free_seg_table (rto [rtx ]);
219
+
220
+ dma_free_cpu_table (rto );
221
+ }
222
+
223
+ static void dma_free_rs_table (unsigned long entry )
224
+ {
225
+ unsigned long * rso = get_rf_rso (entry );
226
+ int rsx ;
227
+
228
+ for (rsx = 0 ; rsx < ZPCI_TABLE_ENTRIES ; rsx ++ )
229
+ if (reg_entry_isvalid (rso [rsx ]))
230
+ dma_free_rt_table (rso [rsx ]);
231
+
232
+ dma_free_cpu_table (rso );
233
+ }
234
+
235
+ static void dma_cleanup_tables (struct s390_domain * domain )
236
+ {
237
+ int rtx , rsx , rfx ;
238
+
239
+ if (!domain -> dma_table )
200
240
return ;
201
241
202
- for (rtx = 0 ; rtx < ZPCI_TABLE_ENTRIES ; rtx ++ )
203
- if (reg_entry_isvalid (table [rtx ]))
204
- dma_free_seg_table (table [rtx ]);
242
+ switch (domain -> origin_type ) {
243
+ case ZPCI_TABLE_TYPE_RFX :
244
+ for (rfx = 0 ; rfx < ZPCI_TABLE_ENTRIES ; rfx ++ )
245
+ if (reg_entry_isvalid (domain -> dma_table [rfx ]))
246
+ dma_free_rs_table (domain -> dma_table [rfx ]);
247
+ break ;
248
+ case ZPCI_TABLE_TYPE_RSX :
249
+ for (rsx = 0 ; rsx < ZPCI_TABLE_ENTRIES ; rsx ++ )
250
+ if (reg_entry_isvalid (domain -> dma_table [rsx ]))
251
+ dma_free_rt_table (domain -> dma_table [rsx ]);
252
+ break ;
253
+ case ZPCI_TABLE_TYPE_RTX :
254
+ for (rtx = 0 ; rtx < ZPCI_TABLE_ENTRIES ; rtx ++ )
255
+ if (reg_entry_isvalid (domain -> dma_table [rtx ]))
256
+ dma_free_seg_table (domain -> dma_table [rtx ]);
257
+ break ;
258
+ default :
259
+ WARN_ONCE (1 , "Invalid IOMMU table (%x)\n" , domain -> origin_type );
260
+ return ;
261
+ }
205
262
206
- dma_free_cpu_table (table );
263
+ dma_free_cpu_table (domain -> dma_table );
207
264
}
208
265
209
266
static unsigned long * dma_alloc_page_table (gfp_t gfp )
@@ -358,7 +415,7 @@ static void s390_iommu_rcu_free_domain(struct rcu_head *head)
358
415
{
359
416
struct s390_domain * s390_domain = container_of (head , struct s390_domain , rcu );
360
417
361
- dma_cleanup_tables (s390_domain -> dma_table );
418
+ dma_cleanup_tables (s390_domain );
362
419
kfree (s390_domain );
363
420
}
364
421
0 commit comments