@@ -301,9 +301,17 @@ static int stub_probe(struct usb_device *udev)
301
301
const char * udev_busid = dev_name (& udev -> dev );
302
302
struct bus_id_priv * busid_priv ;
303
303
int rc = 0 ;
304
+ char save_status ;
304
305
305
306
dev_dbg (& udev -> dev , "Enter probe\n" );
306
307
308
+ /* Not sure if this is our device. Allocate here to avoid
309
+ * calling alloc while holding busid_table lock.
310
+ */
311
+ sdev = stub_device_alloc (udev );
312
+ if (!sdev )
313
+ return - ENOMEM ;
314
+
307
315
/* check we should claim or not by busid_table */
308
316
busid_priv = get_busid_priv (udev_busid );
309
317
if (!busid_priv || (busid_priv -> status == STUB_BUSID_REMOV ) ||
@@ -318,14 +326,14 @@ static int stub_probe(struct usb_device *udev)
318
326
* See driver_probe_device() in driver/base/dd.c
319
327
*/
320
328
rc = - ENODEV ;
321
- goto call_put_busid_priv ;
329
+ goto sdev_free ;
322
330
}
323
331
324
332
if (udev -> descriptor .bDeviceClass == USB_CLASS_HUB ) {
325
333
dev_dbg (& udev -> dev , "%s is a usb hub device... skip!\n" ,
326
334
udev_busid );
327
335
rc = - ENODEV ;
328
- goto call_put_busid_priv ;
336
+ goto sdev_free ;
329
337
}
330
338
331
339
if (!strcmp (udev -> bus -> bus_name , "vhci_hcd" )) {
@@ -334,15 +342,9 @@ static int stub_probe(struct usb_device *udev)
334
342
udev_busid );
335
343
336
344
rc = - ENODEV ;
337
- goto call_put_busid_priv ;
345
+ goto sdev_free ;
338
346
}
339
347
340
- /* ok, this is my device */
341
- sdev = stub_device_alloc (udev );
342
- if (!sdev ) {
343
- rc = - ENOMEM ;
344
- goto call_put_busid_priv ;
345
- }
346
348
347
349
dev_info (& udev -> dev ,
348
350
"usbip-host: register new device (bus %u dev %u)\n" ,
@@ -352,9 +354,13 @@ static int stub_probe(struct usb_device *udev)
352
354
353
355
/* set private data to usb_device */
354
356
dev_set_drvdata (& udev -> dev , sdev );
357
+
355
358
busid_priv -> sdev = sdev ;
356
359
busid_priv -> udev = udev ;
357
360
361
+ save_status = busid_priv -> status ;
362
+ busid_priv -> status = STUB_BUSID_ALLOC ;
363
+
358
364
/*
359
365
* Claim this hub port.
360
366
* It doesn't matter what value we pass as owner
@@ -367,15 +373,16 @@ static int stub_probe(struct usb_device *udev)
367
373
goto err_port ;
368
374
}
369
375
376
+ /* release the busid_lock */
377
+ put_busid_priv (busid_priv );
378
+
370
379
rc = stub_add_files (& udev -> dev );
371
380
if (rc ) {
372
381
dev_err (& udev -> dev , "stub_add_files for %s\n" , udev_busid );
373
382
goto err_files ;
374
383
}
375
- busid_priv -> status = STUB_BUSID_ALLOC ;
376
384
377
- rc = 0 ;
378
- goto call_put_busid_priv ;
385
+ return 0 ;
379
386
380
387
err_files :
381
388
usb_hub_release_port (udev -> parent , udev -> portnum ,
@@ -384,23 +391,24 @@ static int stub_probe(struct usb_device *udev)
384
391
dev_set_drvdata (& udev -> dev , NULL );
385
392
usb_put_dev (udev );
386
393
394
+ /* we already have busid_priv, just lock busid_lock */
395
+ spin_lock (& busid_priv -> busid_lock );
387
396
busid_priv -> sdev = NULL ;
397
+ busid_priv -> status = save_status ;
398
+ sdev_free :
388
399
stub_device_free (sdev );
389
-
390
- call_put_busid_priv :
400
+ /* release the busid_lock */
391
401
put_busid_priv (busid_priv );
402
+
392
403
return rc ;
393
404
}
394
405
395
406
static void shutdown_busid (struct bus_id_priv * busid_priv )
396
407
{
397
- if (busid_priv -> sdev && !busid_priv -> shutdown_busid ) {
398
- busid_priv -> shutdown_busid = 1 ;
399
- usbip_event_add (& busid_priv -> sdev -> ud , SDEV_EVENT_REMOVED );
408
+ usbip_event_add (& busid_priv -> sdev -> ud , SDEV_EVENT_REMOVED );
400
409
401
- /* wait for the stop of the event handler */
402
- usbip_stop_eh (& busid_priv -> sdev -> ud );
403
- }
410
+ /* wait for the stop of the event handler */
411
+ usbip_stop_eh (& busid_priv -> sdev -> ud );
404
412
}
405
413
406
414
/*
@@ -432,6 +440,9 @@ static void stub_disconnect(struct usb_device *udev)
432
440
433
441
dev_set_drvdata (& udev -> dev , NULL );
434
442
443
+ /* release busid_lock before call to remove device files */
444
+ put_busid_priv (busid_priv );
445
+
435
446
/*
436
447
* NOTE: rx/tx threads are invoked for each usb_device.
437
448
*/
@@ -442,18 +453,27 @@ static void stub_disconnect(struct usb_device *udev)
442
453
(struct usb_dev_state * ) udev );
443
454
if (rc ) {
444
455
dev_dbg (& udev -> dev , "unable to release port\n" );
445
- goto call_put_busid_priv ;
456
+ return ;
446
457
}
447
458
448
459
/* If usb reset is called from event handler */
449
460
if (usbip_in_eh (current ))
450
- goto call_put_busid_priv ;
461
+ return ;
462
+
463
+ /* we already have busid_priv, just lock busid_lock */
464
+ spin_lock (& busid_priv -> busid_lock );
465
+ if (!busid_priv -> shutdown_busid )
466
+ busid_priv -> shutdown_busid = 1 ;
467
+ /* release busid_lock */
468
+ put_busid_priv (busid_priv );
451
469
452
470
/* shutdown the current connection */
453
471
shutdown_busid (busid_priv );
454
472
455
473
usb_put_dev (sdev -> udev );
456
474
475
+ /* we already have busid_priv, just lock busid_lock */
476
+ spin_lock (& busid_priv -> busid_lock );
457
477
/* free sdev */
458
478
busid_priv -> sdev = NULL ;
459
479
stub_device_free (sdev );
@@ -462,6 +482,7 @@ static void stub_disconnect(struct usb_device *udev)
462
482
busid_priv -> status = STUB_BUSID_ADDED ;
463
483
464
484
call_put_busid_priv :
485
+ /* release busid_lock */
465
486
put_busid_priv (busid_priv );
466
487
}
467
488
0 commit comments