@@ -137,77 +137,107 @@ static void vfio_ccw_sch_irq(struct subchannel *sch)
137
137
vfio_ccw_fsm_event (private , VFIO_CCW_EVENT_INTERRUPT );
138
138
}
139
139
140
- static void vfio_ccw_free_regions (struct vfio_ccw_private * private )
140
+ static struct vfio_ccw_private * vfio_ccw_alloc_private (struct subchannel * sch )
141
141
{
142
- if (private -> crw_region )
143
- kmem_cache_free (vfio_ccw_crw_region , private -> crw_region );
144
- if (private -> schib_region )
145
- kmem_cache_free (vfio_ccw_schib_region , private -> schib_region );
146
- if (private -> cmd_region )
147
- kmem_cache_free (vfio_ccw_cmd_region , private -> cmd_region );
148
- if (private -> io_region )
149
- kmem_cache_free (vfio_ccw_io_region , private -> io_region );
150
- }
151
-
152
- static int vfio_ccw_sch_probe (struct subchannel * sch )
153
- {
154
- struct pmcw * pmcw = & sch -> schib .pmcw ;
155
142
struct vfio_ccw_private * private ;
156
- int ret = - ENOMEM ;
157
-
158
- if (pmcw -> qf ) {
159
- dev_warn (& sch -> dev , "vfio: ccw: does not support QDIO: %s\n" ,
160
- dev_name (& sch -> dev ));
161
- return - ENODEV ;
162
- }
163
143
164
144
private = kzalloc (sizeof (* private ), GFP_KERNEL );
165
145
if (!private )
166
- return - ENOMEM ;
146
+ return ERR_PTR (- ENOMEM );
147
+
148
+ private -> sch = sch ;
149
+ mutex_init (& private -> io_mutex );
150
+ private -> state = VFIO_CCW_STATE_NOT_OPER ;
151
+ INIT_LIST_HEAD (& private -> crw );
152
+ INIT_WORK (& private -> io_work , vfio_ccw_sch_io_todo );
153
+ INIT_WORK (& private -> crw_work , vfio_ccw_crw_todo );
154
+ atomic_set (& private -> avail , 1 );
167
155
168
156
private -> cp .guest_cp = kcalloc (CCWCHAIN_LEN_MAX , sizeof (struct ccw1 ),
169
157
GFP_KERNEL );
170
158
if (!private -> cp .guest_cp )
171
- goto out_free ;
159
+ goto out_free_private ;
172
160
173
161
private -> io_region = kmem_cache_zalloc (vfio_ccw_io_region ,
174
162
GFP_KERNEL | GFP_DMA );
175
163
if (!private -> io_region )
176
- goto out_free ;
164
+ goto out_free_cp ;
177
165
178
166
private -> cmd_region = kmem_cache_zalloc (vfio_ccw_cmd_region ,
179
167
GFP_KERNEL | GFP_DMA );
180
168
if (!private -> cmd_region )
181
- goto out_free ;
169
+ goto out_free_io ;
182
170
183
171
private -> schib_region = kmem_cache_zalloc (vfio_ccw_schib_region ,
184
172
GFP_KERNEL | GFP_DMA );
185
173
186
174
if (!private -> schib_region )
187
- goto out_free ;
175
+ goto out_free_cmd ;
188
176
189
177
private -> crw_region = kmem_cache_zalloc (vfio_ccw_crw_region ,
190
178
GFP_KERNEL | GFP_DMA );
191
179
192
180
if (!private -> crw_region )
193
- goto out_free ;
181
+ goto out_free_schib ;
182
+ return private ;
183
+
184
+ out_free_schib :
185
+ kmem_cache_free (vfio_ccw_schib_region , private -> schib_region );
186
+ out_free_cmd :
187
+ kmem_cache_free (vfio_ccw_cmd_region , private -> cmd_region );
188
+ out_free_io :
189
+ kmem_cache_free (vfio_ccw_io_region , private -> io_region );
190
+ out_free_cp :
191
+ kfree (private -> cp .guest_cp );
192
+ out_free_private :
193
+ mutex_destroy (& private -> io_mutex );
194
+ kfree (private );
195
+ return ERR_PTR (- ENOMEM );
196
+ }
197
+
198
+ static void vfio_ccw_free_private (struct vfio_ccw_private * private )
199
+ {
200
+ struct vfio_ccw_crw * crw , * temp ;
201
+
202
+ list_for_each_entry_safe (crw , temp , & private -> crw , next ) {
203
+ list_del (& crw -> next );
204
+ kfree (crw );
205
+ }
206
+
207
+ kmem_cache_free (vfio_ccw_crw_region , private -> crw_region );
208
+ kmem_cache_free (vfio_ccw_schib_region , private -> schib_region );
209
+ kmem_cache_free (vfio_ccw_cmd_region , private -> cmd_region );
210
+ kmem_cache_free (vfio_ccw_io_region , private -> io_region );
211
+ kfree (private -> cp .guest_cp );
212
+ mutex_destroy (& private -> io_mutex );
213
+ kfree (private );
214
+ }
215
+
216
+ static int vfio_ccw_sch_probe (struct subchannel * sch )
217
+ {
218
+ struct pmcw * pmcw = & sch -> schib .pmcw ;
219
+ struct vfio_ccw_private * private ;
220
+ int ret = - ENOMEM ;
221
+
222
+ if (pmcw -> qf ) {
223
+ dev_warn (& sch -> dev , "vfio: ccw: does not support QDIO: %s\n" ,
224
+ dev_name (& sch -> dev ));
225
+ return - ENODEV ;
226
+ }
227
+
228
+ private = vfio_ccw_alloc_private (sch );
229
+ if (IS_ERR (private ))
230
+ return PTR_ERR (private );
194
231
195
- private -> sch = sch ;
196
232
dev_set_drvdata (& sch -> dev , private );
197
- mutex_init (& private -> io_mutex );
198
233
199
234
spin_lock_irq (sch -> lock );
200
- private -> state = VFIO_CCW_STATE_NOT_OPER ;
201
235
sch -> isc = VFIO_CCW_ISC ;
202
236
ret = cio_enable_subchannel (sch , (u32 )(unsigned long )sch );
203
237
spin_unlock_irq (sch -> lock );
204
238
if (ret )
205
239
goto out_free ;
206
240
207
- INIT_LIST_HEAD (& private -> crw );
208
- INIT_WORK (& private -> io_work , vfio_ccw_sch_io_todo );
209
- INIT_WORK (& private -> crw_work , vfio_ccw_crw_todo );
210
- atomic_set (& private -> avail , 1 );
211
241
private -> state = VFIO_CCW_STATE_STANDBY ;
212
242
213
243
ret = vfio_ccw_mdev_reg (sch );
@@ -228,31 +258,20 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
228
258
cio_disable_subchannel (sch );
229
259
out_free :
230
260
dev_set_drvdata (& sch -> dev , NULL );
231
- vfio_ccw_free_regions (private );
232
- kfree (private -> cp .guest_cp );
233
- kfree (private );
261
+ vfio_ccw_free_private (private );
234
262
return ret ;
235
263
}
236
264
237
265
static void vfio_ccw_sch_remove (struct subchannel * sch )
238
266
{
239
267
struct vfio_ccw_private * private = dev_get_drvdata (& sch -> dev );
240
- struct vfio_ccw_crw * crw , * temp ;
241
268
242
269
vfio_ccw_sch_quiesce (sch );
243
-
244
- list_for_each_entry_safe (crw , temp , & private -> crw , next ) {
245
- list_del (& crw -> next );
246
- kfree (crw );
247
- }
248
-
249
270
vfio_ccw_mdev_unreg (sch );
250
271
251
272
dev_set_drvdata (& sch -> dev , NULL );
252
273
253
- vfio_ccw_free_regions (private );
254
- kfree (private -> cp .guest_cp );
255
- kfree (private );
274
+ vfio_ccw_free_private (private );
256
275
257
276
VFIO_CCW_MSG_EVENT (4 , "unbound from subchannel %x.%x.%04x\n" ,
258
277
sch -> schid .cssid , sch -> schid .ssid ,
0 commit comments