@@ -121,6 +121,22 @@ static inline int pt_entry_isvalid(unsigned long entry)
121121 return (entry & ZPCI_PTE_VALID_MASK ) == ZPCI_PTE_VALID ;
122122}
123123
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+
124140static inline unsigned long * get_rt_sto (unsigned long entry )
125141{
126142 if ((entry & ZPCI_TABLE_TYPE_MASK ) == ZPCI_TABLE_TYPE_RTX )
@@ -192,18 +208,59 @@ static void dma_free_seg_table(unsigned long entry)
192208 dma_free_cpu_table (sto );
193209}
194210
195- static void dma_cleanup_tables (unsigned long * table )
211+ static void dma_free_rt_table (unsigned long entry )
196212{
213+ unsigned long * rto = get_rs_rto (entry );
197214 int rtx ;
198215
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 )
200240 return ;
201241
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+ }
205262
206- dma_free_cpu_table (table );
263+ dma_free_cpu_table (domain -> dma_table );
207264}
208265
209266static unsigned long * dma_alloc_page_table (gfp_t gfp )
@@ -358,7 +415,7 @@ static void s390_iommu_rcu_free_domain(struct rcu_head *head)
358415{
359416 struct s390_domain * s390_domain = container_of (head , struct s390_domain , rcu );
360417
361- dma_cleanup_tables (s390_domain -> dma_table );
418+ dma_cleanup_tables (s390_domain );
362419 kfree (s390_domain );
363420}
364421
0 commit comments