aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/usbip/stub.h2
-rw-r--r--drivers/usb/usbip/stub_dev.c33
-rw-r--r--drivers/usb/usbip/stub_main.c40
3 files changed, 60 insertions, 15 deletions
diff --git a/drivers/usb/usbip/stub.h b/drivers/usb/usbip/stub.h
index 14a72357800a..35618ceb2791 100644
--- a/drivers/usb/usbip/stub.h
+++ b/drivers/usb/usbip/stub.h
@@ -73,6 +73,7 @@ struct bus_id_priv {
73 struct stub_device *sdev; 73 struct stub_device *sdev;
74 struct usb_device *udev; 74 struct usb_device *udev;
75 char shutdown_busid; 75 char shutdown_busid;
76 spinlock_t busid_lock;
76}; 77};
77 78
78/* stub_priv is allocated from stub_priv_cache */ 79/* stub_priv is allocated from stub_priv_cache */
@@ -83,6 +84,7 @@ extern struct usb_device_driver stub_driver;
83 84
84/* stub_main.c */ 85/* stub_main.c */
85struct bus_id_priv *get_busid_priv(const char *busid); 86struct bus_id_priv *get_busid_priv(const char *busid);
87void put_busid_priv(struct bus_id_priv *bid);
86int del_match_busid(char *busid); 88int del_match_busid(char *busid);
87void stub_device_cleanup_urbs(struct stub_device *sdev); 89void stub_device_cleanup_urbs(struct stub_device *sdev);
88 90
diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
index 9d0425113c4b..c0d6ff1baa72 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -300,7 +300,7 @@ static int stub_probe(struct usb_device *udev)
300 struct stub_device *sdev = NULL; 300 struct stub_device *sdev = NULL;
301 const char *udev_busid = dev_name(&udev->dev); 301 const char *udev_busid = dev_name(&udev->dev);
302 struct bus_id_priv *busid_priv; 302 struct bus_id_priv *busid_priv;
303 int rc; 303 int rc = 0;
304 304
305 dev_dbg(&udev->dev, "Enter probe\n"); 305 dev_dbg(&udev->dev, "Enter probe\n");
306 306
@@ -317,13 +317,15 @@ static int stub_probe(struct usb_device *udev)
317 * other matched drivers by the driver core. 317 * other matched drivers by the driver core.
318 * See driver_probe_device() in driver/base/dd.c 318 * See driver_probe_device() in driver/base/dd.c
319 */ 319 */
320 return -ENODEV; 320 rc = -ENODEV;
321 goto call_put_busid_priv;
321 } 322 }
322 323
323 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) { 324 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
324 dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n", 325 dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
325 udev_busid); 326 udev_busid);
326 return -ENODEV; 327 rc = -ENODEV;
328 goto call_put_busid_priv;
327 } 329 }
328 330
329 if (!strcmp(udev->bus->bus_name, "vhci_hcd")) { 331 if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
@@ -331,13 +333,16 @@ static int stub_probe(struct usb_device *udev)
331 "%s is attached on vhci_hcd... skip!\n", 333 "%s is attached on vhci_hcd... skip!\n",
332 udev_busid); 334 udev_busid);
333 335
334 return -ENODEV; 336 rc = -ENODEV;
337 goto call_put_busid_priv;
335 } 338 }
336 339
337 /* ok, this is my device */ 340 /* ok, this is my device */
338 sdev = stub_device_alloc(udev); 341 sdev = stub_device_alloc(udev);
339 if (!sdev) 342 if (!sdev) {
340 return -ENOMEM; 343 rc = -ENOMEM;
344 goto call_put_busid_priv;
345 }
341 346
342 dev_info(&udev->dev, 347 dev_info(&udev->dev,
343 "usbip-host: register new device (bus %u dev %u)\n", 348 "usbip-host: register new device (bus %u dev %u)\n",
@@ -369,7 +374,9 @@ static int stub_probe(struct usb_device *udev)
369 } 374 }
370 busid_priv->status = STUB_BUSID_ALLOC; 375 busid_priv->status = STUB_BUSID_ALLOC;
371 376
372 return 0; 377 rc = 0;
378 goto call_put_busid_priv;
379
373err_files: 380err_files:
374 usb_hub_release_port(udev->parent, udev->portnum, 381 usb_hub_release_port(udev->parent, udev->portnum,
375 (struct usb_dev_state *) udev); 382 (struct usb_dev_state *) udev);
@@ -379,6 +386,9 @@ err_port:
379 386
380 busid_priv->sdev = NULL; 387 busid_priv->sdev = NULL;
381 stub_device_free(sdev); 388 stub_device_free(sdev);
389
390call_put_busid_priv:
391 put_busid_priv(busid_priv);
382 return rc; 392 return rc;
383} 393}
384 394
@@ -417,7 +427,7 @@ static void stub_disconnect(struct usb_device *udev)
417 /* get stub_device */ 427 /* get stub_device */
418 if (!sdev) { 428 if (!sdev) {
419 dev_err(&udev->dev, "could not get device"); 429 dev_err(&udev->dev, "could not get device");
420 return; 430 goto call_put_busid_priv;
421 } 431 }
422 432
423 dev_set_drvdata(&udev->dev, NULL); 433 dev_set_drvdata(&udev->dev, NULL);
@@ -432,12 +442,12 @@ static void stub_disconnect(struct usb_device *udev)
432 (struct usb_dev_state *) udev); 442 (struct usb_dev_state *) udev);
433 if (rc) { 443 if (rc) {
434 dev_dbg(&udev->dev, "unable to release port\n"); 444 dev_dbg(&udev->dev, "unable to release port\n");
435 return; 445 goto call_put_busid_priv;
436 } 446 }
437 447
438 /* If usb reset is called from event handler */ 448 /* If usb reset is called from event handler */
439 if (usbip_in_eh(current)) 449 if (usbip_in_eh(current))
440 return; 450 goto call_put_busid_priv;
441 451
442 /* shutdown the current connection */ 452 /* shutdown the current connection */
443 shutdown_busid(busid_priv); 453 shutdown_busid(busid_priv);
@@ -450,6 +460,9 @@ static void stub_disconnect(struct usb_device *udev)
450 460
451 if (busid_priv->status == STUB_BUSID_ALLOC) 461 if (busid_priv->status == STUB_BUSID_ALLOC)
452 busid_priv->status = STUB_BUSID_ADDED; 462 busid_priv->status = STUB_BUSID_ADDED;
463
464call_put_busid_priv:
465 put_busid_priv(busid_priv);
453} 466}
454 467
455#ifdef CONFIG_PM 468#ifdef CONFIG_PM
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index 587b9bc10042..41c7b9de2a92 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -26,6 +26,8 @@ static spinlock_t busid_table_lock;
26 26
27static void init_busid_table(void) 27static void init_busid_table(void)
28{ 28{
29 int i;
30
29 /* 31 /*
30 * This also sets the bus_table[i].status to 32 * This also sets the bus_table[i].status to
31 * STUB_BUSID_OTHER, which is 0. 33 * STUB_BUSID_OTHER, which is 0.
@@ -33,6 +35,9 @@ static void init_busid_table(void)
33 memset(busid_table, 0, sizeof(busid_table)); 35 memset(busid_table, 0, sizeof(busid_table));
34 36
35 spin_lock_init(&busid_table_lock); 37 spin_lock_init(&busid_table_lock);
38
39 for (i = 0; i < MAX_BUSID; i++)
40 spin_lock_init(&busid_table[i].busid_lock);
36} 41}
37 42
38/* 43/*
@@ -44,15 +49,20 @@ static int get_busid_idx(const char *busid)
44 int i; 49 int i;
45 int idx = -1; 50 int idx = -1;
46 51
47 for (i = 0; i < MAX_BUSID; i++) 52 for (i = 0; i < MAX_BUSID; i++) {
53 spin_lock(&busid_table[i].busid_lock);
48 if (busid_table[i].name[0]) 54 if (busid_table[i].name[0])
49 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) { 55 if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
50 idx = i; 56 idx = i;
57 spin_unlock(&busid_table[i].busid_lock);
51 break; 58 break;
52 } 59 }
60 spin_unlock(&busid_table[i].busid_lock);
61 }
53 return idx; 62 return idx;
54} 63}
55 64
65/* Returns holding busid_lock. Should call put_busid_priv() to unlock */
56struct bus_id_priv *get_busid_priv(const char *busid) 66struct bus_id_priv *get_busid_priv(const char *busid)
57{ 67{
58 int idx; 68 int idx;
@@ -60,13 +70,21 @@ struct bus_id_priv *get_busid_priv(const char *busid)
60 70
61 spin_lock(&busid_table_lock); 71 spin_lock(&busid_table_lock);
62 idx = get_busid_idx(busid); 72 idx = get_busid_idx(busid);
63 if (idx >= 0) 73 if (idx >= 0) {
64 bid = &(busid_table[idx]); 74 bid = &(busid_table[idx]);
75 /* get busid_lock before returning */
76 spin_lock(&bid->busid_lock);
77 }
65 spin_unlock(&busid_table_lock); 78 spin_unlock(&busid_table_lock);
66 79
67 return bid; 80 return bid;
68} 81}
69 82
83void put_busid_priv(struct bus_id_priv *bid)
84{
85 spin_unlock(&bid->busid_lock);
86}
87
70static int add_match_busid(char *busid) 88static int add_match_busid(char *busid)
71{ 89{
72 int i; 90 int i;
@@ -79,15 +97,19 @@ static int add_match_busid(char *busid)
79 goto out; 97 goto out;
80 } 98 }
81 99
82 for (i = 0; i < MAX_BUSID; i++) 100 for (i = 0; i < MAX_BUSID; i++) {
101 spin_lock(&busid_table[i].busid_lock);
83 if (!busid_table[i].name[0]) { 102 if (!busid_table[i].name[0]) {
84 strlcpy(busid_table[i].name, busid, BUSID_SIZE); 103 strlcpy(busid_table[i].name, busid, BUSID_SIZE);
85 if ((busid_table[i].status != STUB_BUSID_ALLOC) && 104 if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
86 (busid_table[i].status != STUB_BUSID_REMOV)) 105 (busid_table[i].status != STUB_BUSID_REMOV))
87 busid_table[i].status = STUB_BUSID_ADDED; 106 busid_table[i].status = STUB_BUSID_ADDED;
88 ret = 0; 107 ret = 0;
108 spin_unlock(&busid_table[i].busid_lock);
89 break; 109 break;
90 } 110 }
111 spin_unlock(&busid_table[i].busid_lock);
112 }
91 113
92out: 114out:
93 spin_unlock(&busid_table_lock); 115 spin_unlock(&busid_table_lock);
@@ -108,6 +130,8 @@ int del_match_busid(char *busid)
108 /* found */ 130 /* found */
109 ret = 0; 131 ret = 0;
110 132
133 spin_lock(&busid_table[idx].busid_lock);
134
111 if (busid_table[idx].status == STUB_BUSID_OTHER) 135 if (busid_table[idx].status == STUB_BUSID_OTHER)
112 memset(busid_table[idx].name, 0, BUSID_SIZE); 136 memset(busid_table[idx].name, 0, BUSID_SIZE);
113 137
@@ -115,6 +139,7 @@ int del_match_busid(char *busid)
115 (busid_table[idx].status != STUB_BUSID_ADDED)) 139 (busid_table[idx].status != STUB_BUSID_ADDED))
116 busid_table[idx].status = STUB_BUSID_REMOV; 140 busid_table[idx].status = STUB_BUSID_REMOV;
117 141
142 spin_unlock(&busid_table[idx].busid_lock);
118out: 143out:
119 spin_unlock(&busid_table_lock); 144 spin_unlock(&busid_table_lock);
120 145
@@ -127,9 +152,12 @@ static ssize_t match_busid_show(struct device_driver *drv, char *buf)
127 char *out = buf; 152 char *out = buf;
128 153
129 spin_lock(&busid_table_lock); 154 spin_lock(&busid_table_lock);
130 for (i = 0; i < MAX_BUSID; i++) 155 for (i = 0; i < MAX_BUSID; i++) {
156 spin_lock(&busid_table[i].busid_lock);
131 if (busid_table[i].name[0]) 157 if (busid_table[i].name[0])
132 out += sprintf(out, "%s ", busid_table[i].name); 158 out += sprintf(out, "%s ", busid_table[i].name);
159 spin_unlock(&busid_table[i].busid_lock);
160 }
133 spin_unlock(&busid_table_lock); 161 spin_unlock(&busid_table_lock);
134 out += sprintf(out, "\n"); 162 out += sprintf(out, "\n");
135 163
@@ -204,7 +232,7 @@ static void stub_device_rebind(void)
204 } 232 }
205 spin_unlock(&busid_table_lock); 233 spin_unlock(&busid_table_lock);
206 234
207 /* now run rebind */ 235 /* now run rebind - no need to hold locks. driver files are removed */
208 for (i = 0; i < MAX_BUSID; i++) { 236 for (i = 0; i < MAX_BUSID; i++) {
209 if (busid_table[i].name[0] && 237 if (busid_table[i].name[0] &&
210 busid_table[i].shutdown_busid) { 238 busid_table[i].shutdown_busid) {
@@ -234,6 +262,8 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf,
234 262
235 /* mark the device for deletion so probe ignores it during rescan */ 263 /* mark the device for deletion so probe ignores it during rescan */
236 bid->status = STUB_BUSID_OTHER; 264 bid->status = STUB_BUSID_OTHER;
265 /* release the busid lock */
266 put_busid_priv(bid);
237 267
238 ret = do_rebind((char *) buf, bid); 268 ret = do_rebind((char *) buf, bid);
239 if (ret < 0) 269 if (ret < 0)