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