@@ -79,18 +79,44 @@ static void s390_domain_free(struct iommu_domain *domain)
79
79
{
80
80
struct s390_domain * s390_domain = to_s390_domain (domain );
81
81
82
+ WARN_ON (!list_empty (& s390_domain -> devices ));
82
83
dma_cleanup_tables (s390_domain -> dma_table );
83
84
kfree (s390_domain );
84
85
}
85
86
87
+ static void __s390_iommu_detach_device (struct zpci_dev * zdev )
88
+ {
89
+ struct s390_domain * s390_domain = zdev -> s390_domain ;
90
+ struct s390_domain_device * domain_device , * tmp ;
91
+ unsigned long flags ;
92
+
93
+ if (!s390_domain )
94
+ return ;
95
+
96
+ spin_lock_irqsave (& s390_domain -> list_lock , flags );
97
+ list_for_each_entry_safe (domain_device , tmp , & s390_domain -> devices ,
98
+ list ) {
99
+ if (domain_device -> zdev == zdev ) {
100
+ list_del (& domain_device -> list );
101
+ kfree (domain_device );
102
+ break ;
103
+ }
104
+ }
105
+ spin_unlock_irqrestore (& s390_domain -> list_lock , flags );
106
+
107
+ zpci_unregister_ioat (zdev , 0 );
108
+ zdev -> s390_domain = NULL ;
109
+ zdev -> dma_table = NULL ;
110
+ }
111
+
86
112
static int s390_iommu_attach_device (struct iommu_domain * domain ,
87
113
struct device * dev )
88
114
{
89
115
struct s390_domain * s390_domain = to_s390_domain (domain );
90
116
struct zpci_dev * zdev = to_zpci_dev (dev );
91
117
struct s390_domain_device * domain_device ;
92
118
unsigned long flags ;
93
- int cc , rc ;
119
+ int cc , rc = 0 ;
94
120
95
121
if (!zdev )
96
122
return - ENODEV ;
@@ -99,24 +125,18 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
99
125
if (!domain_device )
100
126
return - ENOMEM ;
101
127
102
- if (zdev -> dma_table && !zdev -> s390_domain ) {
103
- cc = zpci_dma_exit_device (zdev );
104
- if (cc ) {
105
- rc = - EIO ;
106
- goto out_free ;
107
- }
108
- }
109
-
110
128
if (zdev -> s390_domain )
111
- zpci_unregister_ioat (zdev , 0 );
129
+ __s390_iommu_detach_device (zdev );
130
+ else if (zdev -> dma_table )
131
+ zpci_dma_exit_device (zdev );
112
132
113
- zdev -> dma_table = s390_domain -> dma_table ;
114
133
cc = zpci_register_ioat (zdev , 0 , zdev -> start_dma , zdev -> end_dma ,
115
- virt_to_phys (zdev -> dma_table ));
134
+ virt_to_phys (s390_domain -> dma_table ));
116
135
if (cc ) {
117
136
rc = - EIO ;
118
- goto out_restore ;
137
+ goto out_free ;
119
138
}
139
+ zdev -> dma_table = s390_domain -> dma_table ;
120
140
121
141
spin_lock_irqsave (& s390_domain -> list_lock , flags );
122
142
/* First device defines the DMA range limits */
@@ -127,9 +147,9 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
127
147
/* Allow only devices with identical DMA range limits */
128
148
} else if (domain -> geometry .aperture_start != zdev -> start_dma ||
129
149
domain -> geometry .aperture_end != zdev -> end_dma ) {
130
- rc = - EINVAL ;
131
150
spin_unlock_irqrestore (& s390_domain -> list_lock , flags );
132
- goto out_restore ;
151
+ rc = - EINVAL ;
152
+ goto out_unregister ;
133
153
}
134
154
domain_device -> zdev = zdev ;
135
155
zdev -> s390_domain = s390_domain ;
@@ -138,14 +158,9 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
138
158
139
159
return 0 ;
140
160
141
- out_restore :
142
- if (!zdev -> s390_domain ) {
143
- zpci_dma_init_device (zdev );
144
- } else {
145
- zdev -> dma_table = zdev -> s390_domain -> dma_table ;
146
- zpci_register_ioat (zdev , 0 , zdev -> start_dma , zdev -> end_dma ,
147
- virt_to_phys (zdev -> dma_table ));
148
- }
161
+ out_unregister :
162
+ zpci_unregister_ioat (zdev , 0 );
163
+ zdev -> dma_table = NULL ;
149
164
out_free :
150
165
kfree (domain_device );
151
166
@@ -155,32 +170,12 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
155
170
static void s390_iommu_detach_device (struct iommu_domain * domain ,
156
171
struct device * dev )
157
172
{
158
- struct s390_domain * s390_domain = to_s390_domain (domain );
159
173
struct zpci_dev * zdev = to_zpci_dev (dev );
160
- struct s390_domain_device * domain_device , * tmp ;
161
- unsigned long flags ;
162
- int found = 0 ;
163
174
164
- if (!zdev )
165
- return ;
175
+ WARN_ON (zdev -> s390_domain != to_s390_domain (domain ));
166
176
167
- spin_lock_irqsave (& s390_domain -> list_lock , flags );
168
- list_for_each_entry_safe (domain_device , tmp , & s390_domain -> devices ,
169
- list ) {
170
- if (domain_device -> zdev == zdev ) {
171
- list_del (& domain_device -> list );
172
- kfree (domain_device );
173
- found = 1 ;
174
- break ;
175
- }
176
- }
177
- spin_unlock_irqrestore (& s390_domain -> list_lock , flags );
178
-
179
- if (found && (zdev -> s390_domain == s390_domain )) {
180
- zdev -> s390_domain = NULL ;
181
- zpci_unregister_ioat (zdev , 0 );
182
- zpci_dma_init_device (zdev );
183
- }
177
+ __s390_iommu_detach_device (zdev );
178
+ zpci_dma_init_device (zdev );
184
179
}
185
180
186
181
static struct iommu_device * s390_iommu_probe_device (struct device * dev )
@@ -198,24 +193,13 @@ static struct iommu_device *s390_iommu_probe_device(struct device *dev)
198
193
static void s390_iommu_release_device (struct device * dev )
199
194
{
200
195
struct zpci_dev * zdev = to_zpci_dev (dev );
201
- struct iommu_domain * domain ;
202
196
203
197
/*
204
- * This is a workaround for a scenario where the IOMMU API common code
205
- * "forgets" to call the detach_dev callback: After binding a device
206
- * to vfio-pci and completing the VFIO_SET_IOMMU ioctl (which triggers
207
- * the attach_dev), removing the device via
208
- * "echo 1 > /sys/bus/pci/devices/.../remove" won't trigger detach_dev,
209
- * only release_device will be called via the BUS_NOTIFY_REMOVED_DEVICE
210
- * notifier.
211
- *
212
- * So let's call detach_dev from here if it hasn't been called before.
198
+ * release_device is expected to detach any domain currently attached
199
+ * to the device, but keep it attached to other devices in the group.
213
200
*/
214
- if (zdev && zdev -> s390_domain ) {
215
- domain = iommu_get_domain_for_dev (dev );
216
- if (domain )
217
- s390_iommu_detach_device (domain , dev );
218
- }
201
+ if (zdev )
202
+ __s390_iommu_detach_device (zdev );
219
203
}
220
204
221
205
static int s390_iommu_update_trans (struct s390_domain * s390_domain ,
0 commit comments